[cig-commits] commit: Merge Elastic and Stokes

Mercurial hg at geodynamics.org
Thu Jun 7 13:36:11 PDT 2012


changeset:   282:c77b196abc8c
tag:         tip
parent:      254:2816cd6f8030
parent:      281:dc04c13db402
user:        Walter Landry <wlandry at caltech.edu>
date:        Thu Jun 07 13:34:24 2012 -0700
files:       input/fault.input input/fault3D.input input/sinker.input input/sinker3D.input src/Elastic/FAC.h src/Elastic/FAC/FAC.C src/Elastic/FACOps.h src/Elastic/FACSolver.h src/Elastic/FACSolver/FACSolver.C src/Elastic/HypreSolver.C src/Elastic/HypreSolver.h src/Elastic/P_Boundary_Refine.h src/Elastic/P_Boundary_Refine/Update_P_2D.C src/Elastic/P_Boundary_Refine/Update_P_3D.C src/Elastic/P_Boundary_Refine/refine.C src/Elastic/P_Refine.C src/Elastic/P_Refine.h src/Elastic/P_Refine_Patch_Strategy.h src/Elastic/Resid_Coarsen.C src/Elastic/Resid_Coarsen.h src/Elastic/V_Boundary_Refine.h src/Elastic/V_Boundary_Refine/Update_V_2D.C src/Elastic/V_Boundary_Refine/Update_V_3D.C src/Elastic/V_Boundary_Refine/refine.C src/Elastic/V_Coarsen.h src/Elastic/V_Coarsen/coarsen_2D.C src/Elastic/V_Coarsen/coarsen_3D.C src/Elastic/V_Coarsen_Patch_Strategy.h src/Elastic/V_Coarsen_Patch_Strategy/postprocessCoarsen_2D.C src/Elastic/V_Coarsen_Patch_Strategy/postprocessCoarsen_3D.C src/Elastic/V_Refine.h src/Elastic/V_Refine/refine.C src/Elastic/V_Refine/refine_along_line.C src/Elastic/V_Refine_Patch_Strategy.h src/Elastic/dRc_dp.h src/Elastic/dRm_dv.h src/Elastic/set_boundary.h src/Stokes/FAC.h src/Stokes/FAC/FAC.C src/Stokes/FACOps.h src/Stokes/FACSolver.h src/Stokes/FACSolver/FACSolver.C src/Stokes/HypreSolver.C src/Stokes/HypreSolver.h src/Stokes/P_Boundary_Refine.h src/Stokes/P_Boundary_Refine/Update_P_2D.C src/Stokes/P_Boundary_Refine/Update_P_3D.C src/Stokes/P_Boundary_Refine/refine.C src/Stokes/P_Refine.C src/Stokes/P_Refine.h src/Stokes/P_Refine_Patch_Strategy.h src/Stokes/Resid_Coarsen.h src/Stokes/V_Boundary_Refine.h src/Stokes/V_Boundary_Refine/Update_V_2D.C src/Stokes/V_Boundary_Refine/Update_V_3D.C src/Stokes/V_Boundary_Refine/refine.C src/Stokes/V_Coarsen.h src/Stokes/V_Coarsen/coarsen_2D.C src/Stokes/V_Coarsen/coarsen_3D.C src/Stokes/V_Coarsen_Patch_Strategy.h src/Stokes/V_Coarsen_Patch_Strategy/postprocessCoarsen_2D.C src/Stokes/V_Coarsen_Patch_Strategy/postprocessCoarsen_3D.C src/Stokes/V_Refine.C src/Stokes/V_Refine.h src/Stokes/V_Refine_Patch_Strategy.h src/Stokes/dRc_dp.h src/Stokes/dRm_dv.h src/Stokes/set_boundary.h src/Stokes/viscosity_coarsen.h src/main.C src/quad_offset_interpolate.h src/solve_system.h wscript
description:
Merge Elastic and Stokes


diff -r 2816cd6f8030 -r c77b196abc8c input/fault.input
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/input/fault.input	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,235 @@
+/*************************************************************************
+ *
+ * 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:   Input file for example FAC Stokes solver 
+ *
+ ************************************************************************/
+// This is the input file for the 2D FAC example
+// demonstrating changes in boundary conditions.
+//
+// Note that using constant refine prolongation
+// lead to slower convergence.
+
+Main {
+    dim = 2
+    // Base name for output files.
+    base_name = "fault"
+    // Whether to log all nodes in a parallel run.
+    log_all_nodes = TRUE
+    // Visualization writers to write files for.
+    vis_writer = "Vizamrai", "VisIt"
+}
+
+Elastic {
+    // The FACStokes class is the "user class" in this example.
+    // It owns the solver and contains the code to set up the solver.
+    // The inputs for FACStokes is simply the inputs for the individual
+    // parts owned by the FACStokes class.
+    adaption_threshold = 1.0e-1
+    min_full_refinement_level = 1
+
+    lambda_ijk= 2, 2
+    lambda_coord_min= -0.001, -0.001
+    lambda_coord_max= 1.001, 1.001
+    lambda_data= 
+    1, 1,
+    1, 1
+
+    mu_ijk= 3, 3
+    mu_coord_min= -0.001, -0.001
+    mu_coord_max= 1.001, 1.001
+    mu_data= 1, 1, 1,
+    1, 1, 1,
+    1, 1, 1
+
+    v_rhs_ijk= 11, 11
+    v_rhs_coord_min= -0.001, -0.001
+    v_rhs_coord_max= 1.001, 1.001
+    // v_rhs_data= 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1.03, 1.03, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1.03, 1.03, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+
+    v_rhs_data= 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 3, -3, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 3, -3, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+
+    // p_initial_ijk= 2, 2
+    // p_initial_coord_min= 0, 0
+    // p_initial_coord_max= 1, 1
+    // p_initial_data= 1,1,0,0
+
+    fac_solver {
+        // This is the input for the cell-centered Stokes FAC solver
+        // class in the SAMRAI library.
+        enable_logging = TRUE   // Bool flag to switch logging on/off
+        max_cycles = 100         // Max number of FAC cycles to use
+        residual_tol = 1e-3     // Residual tolerance to solve for
+        num_pre_sweeps = 8      // Number of presmoothing sweeps to use
+        num_post_sweeps = 8     // Number of postsmoothing sweeps to use
+        smoothing_choice = "Tackley"
+        coarse_solver_choice = "Tackley"
+        // smoothing_choice = "Gerya"
+        // coarse_solver_choice = "Gerya"
+        coarse_solver_max_iterations = 32
+        coarse_solver_tolerance = 1e-5
+        // p_prolongation_method = "P_MDPI_REFINE"
+        p_prolongation_method = "P_REFINE"
+        v_prolongation_method = "V_REFINE"
+        p_rrestriction_method = "RESID_COARSEN"
+    }
+    bc_coefs {
+        // These are the boundary condition specifications.  The number
+        // after "boundary_" is the location index of the boundary.
+        // The inputs are arrays of strings where the first string
+        // indicates the type of values you want to set.  "slope" means
+        // boundary slope, "value" means boundary value, and "coefficients"
+        // mean the raw Robin boundary condition coefficients.
+        // The remaining strings are converted into numbers as
+        // appropriate for what boundary condition you specified with
+        // the first string.  Other boundary conditions are possible.
+        // see the solv_RobinBcCoefStrategy class.
+        // Examples:
+        // boundary_0 = "slope", "0"
+        // boundary_1 = "coefficients", "0", "0"
+        // boundary_2 = "value", "0"
+        // boundary_3 = "value", "0"
+        boundary_0 = "value", "0"
+        boundary_1 = "value", "0"
+        boundary_2 = "value", "0"
+        boundary_3 = "value", "0"
+    }
+}
+
+CartesianGridGeometry {
+    //  Specify lower/upper corners of the computational domain and a
+    //  set of non-overlapping boxes defining domain interior.  If union 
+    //  of boxes is not a parallelpiped, lower/upper corner data corresponds 
+    //  to min/max corner indices over all boxes given.
+    //  x_lo  -- (double array) lower corner of computational domain [REQD]
+    //  x_up  -- (double array) upper corner of computational domain [REQD]
+    //  domain_boxes  -- (box array) set of boxes that define interior of 
+    //                   physical domain. [REQD]
+    //  periodic_dimension -- (int array) coordinate directions in which 
+    //                        domain is periodic.  Zero indicates not
+    //                        periodic, non-zero value indicates periodicity.
+    //                        [0]
+    // domain_boxes = [(0,0), (15,15)]
+    domain_boxes = [(0,0), (3,3)]
+    x_lo         = 0, 0
+    x_up         = 1, 1
+}
+
+StandardTagAndInitialize {
+    tagging_method = "GRADIENT_DETECTOR"
+}
+
+PatchHierarchy {
+    // Information used to create patches in AMR hierarchy.
+    // max_levels -- (int) max number of mesh levels in hierarchy [REQD]
+    // 
+    // For most of the following parameters, the number of precribed data
+    // values need not match the number of levels in the hierarchy 
+    // (determined by max_levels).  If more values are given than number 
+    // of levels, extraneous values will be ignored.  If less are give, then
+    // values that correspond to individual levels will apply to those 
+    // levels.  Missing values will be taken from those for the finest
+    // level specified.
+    //
+    // ratio_to_coarser {
+    //   level_1 -- (int array) ratio between index spaces on 
+    //              level 1 to level 0 [REQD]
+    //   level_2 -- (int array)  ratio between index spaces on 
+    //              level 2 to level 1 [REQD]
+    //   etc....
+    // }
+    // largest_patch_size {
+    //   level_0 -- (int array) largest patch allowed on level 0. 
+    //              [REQD]    
+    //   level_1 -- (int array)    "       "      "   "  level 1 
+    //              [level 0 entry]
+    //   etc....                       
+    // }
+    max_levels = 5
+    proper_nesting_buffer = 2, 2, 2, 2, 2, 2
+    ratio_to_coarser {
+        level_1            = 2, 2
+        level_2            = 2, 2
+        level_3            = 2, 2
+        level_4            = 2, 2
+        level_5            = 2, 2
+        level_6            = 2, 2
+    }
+    largest_patch_size {
+        // level_0 = 32, 32
+        // level_0 = 8, 8
+        level_0 = -1, -1
+        // all finer levels will use same values as level_0...
+    }
+}
+
+GriddingAlgorithm {
+    enforce_proper_nesting = TRUE
+    extend_to_domain_boundary = FALSE
+    proper_nesting_buffer = 2, 2, 2, 2, 2, 2
+    // load_balance = FALSE
+    efficiency_tolerance = 0.80
+    combine_efficiency = 0.75
+    // write_regrid_boxes = TRUE
+    // read_regrid_boxes = TRUE
+    // regrid_boxes_filename = "grid"
+    check_nonrefined_tags = "ERROR"
+    check_overlapping_patches = "ERROR"
+    extend_tags_to_bdry = TRUE
+    sequentialize_patch_indices = TRUE
+    barrier_before_regrid = TRUE
+    barrier_before_find_refinement = TRUE
+    barrier_before_cluster = TRUE
+    barrier_before_nest = TRUE
+    barrier_before_limit = TRUE
+    barrier_before_extend = TRUE
+    barrier_before_balance = TRUE
+    barrier_after_find_refinement = TRUE
+    coalesce_boxes = FALSE
+}
diff -r 2816cd6f8030 -r c77b196abc8c input/fault3D.input
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/input/fault3D.input	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,980 @@
+/*************************************************************************
+ *
+ * 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:   Input file for example FAC Stokes solver 
+ *
+ ************************************************************************/
+// This is the input file for the 2D FAC example
+// demonstrating changes in boundary conditions.
+//
+// Note that using constant refine prolongation
+// lead to slower convergence.
+
+Main {
+    dim = 3
+    // Base name for output files.
+    base_name = "fault3D"
+    // Whether to log all nodes in a parallel run.
+    log_all_nodes = TRUE
+    // Visualization writers to write files for.
+    vis_writer = "Vizamrai", "VisIt"
+}
+
+Elastic {
+    // The FACStokes class is the "user class" in this example.
+    // It owns the solver and contains the code to set up the solver.
+    // The inputs for FACStokes is simply the inputs for the individual
+    // parts owned by the FACStokes class.
+    adaption_threshold = 1.0e-3
+    min_full_refinement_level = 1
+
+    lambda_ijk= 2, 2, 2
+    lambda_coord_min= -0.001, -0.001, -0.001
+    lambda_coord_max= 1.001, 1.001, 1.001
+    lambda_data= 1, 1,
+    1, 1, 
+    1, 1,
+    1, 1
+
+    mu_ijk= 2, 2, 2
+    mu_coord_min= -0.001, -0.001, -0.001
+    mu_coord_max= 1.001, 1.001, 1.001
+    mu_data= 1, 1,
+    1, 1, 
+    1, 1,
+    1, 1
+
+    v_rhs_ijk= 11, 11, 11
+    v_rhs_coord_min= -0.001, -0.001, -0.001
+    v_rhs_coord_max= 1.001, 1.001, 1.001
+    v_rhs_data= 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0.03, 0.03, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0.03, 0.03, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0.03, 0.03, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0.03, 0.03, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+
+    // v_rhs_data= 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1.03, 1.03, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1.03, 1.03, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1.03, 1.03, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1.03, 1.03, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+
+    // p_initial_ijk= 2, 2, 2
+    // p_initial_coord_min= 0, 0, 0
+    // p_initial_coord_max= 1, 1, 1
+    // p_initial_data= 1,1,0,0, 1,1,0,0
+
+    fac_solver {
+        // This is the input for the cell-centered Stokes FAC solver
+        // class in the SAMRAI library.
+        enable_logging = TRUE   // Bool flag to switch logging on/off
+        max_cycles = 100         // Max number of FAC cycles to use
+        residual_tol = 1e-3     // Residual tolerance to solve for
+        num_pre_sweeps =  8      // Number of presmoothing sweeps to use
+        num_post_sweeps =  8     // Number of postsmoothing sweeps to use
+        smoothing_choice = "Tackley"
+        coarse_solver_choice = "Tackley"
+        // smoothing_choice = "Gerya"
+        // coarse_solver_choice = "Gerya"
+        coarse_solver_max_iterations =  32
+        coarse_solver_tolerance = 1e-12
+        // p_prolongation_method = "P_MDPI_REFINE"
+        p_prolongation_method = "P_REFINE"
+        v_prolongation_method = "V_REFINE"
+        p_rrestriction_method = "RESID_COARSEN"
+    }
+    bc_coefs {
+        // These are the boundary condition specifications.  The number
+        // after "boundary_" is the location index of the boundary.
+        // The inputs are arrays of strings where the first string
+        // indicates the type of values you want to set.  "slope" means
+        // boundary slope, "value" means boundary value, and "coefficients"
+        // mean the raw Robin boundary condition coefficients.
+        // The remaining strings are converted into numbers as
+        // appropriate for what boundary condition you specified with
+        // the first string.  Other boundary conditions are possible.
+        // see the solv_RobinBcCoefStrategy class.
+        // Examples:
+        // boundary_0 = "slope", "0"
+        // boundary_1 = "coefficients", "0", "0"
+        // boundary_2 = "value", "0"
+        // boundary_3 = "value", "0"
+        boundary_0 = "value", "0"
+        boundary_1 = "value", "0"
+        boundary_2 = "value", "0"
+        boundary_3 = "value", "0"
+    }
+}
+
+CartesianGridGeometry {
+    //  Specify lower/upper corners of the computational domain and a
+    //  set of non-overlapping boxes defining domain interior.  If union 
+    //  of boxes is not a parallelpiped, lower/upper corner data corresponds 
+    //  to min/max corner indices over all boxes given.
+    //  x_lo  -- (double array) lower corner of computational domain [REQD]
+    //  x_up  -- (double array) upper corner of computational domain [REQD]
+    //  domain_boxes  -- (box array) set of boxes that define interior of 
+    //                   physical domain. [REQD]
+    //  periodic_dimension -- (int array) coordinate directions in which 
+    //                        domain is periodic.  Zero indicates not
+    //                        periodic, non-zero value indicates periodicity.
+    //                        [0]
+    // domain_boxes = [(0,0), (15,15)]
+    domain_boxes = [(0,0,0), (3,3,3)]
+    x_lo         = 0, 0, 0
+    x_up         = 1, 1, 1
+}
+
+StandardTagAndInitialize {
+    tagging_method = "GRADIENT_DETECTOR"
+}
+
+PatchHierarchy {
+    // Information used to create patches in AMR hierarchy.
+    // max_levels -- (int) max number of mesh levels in hierarchy [REQD]
+    // 
+    // For most of the following parameters, the number of precribed data
+    // values need not match the number of levels in the hierarchy 
+    // (determined by max_levels).  If more values are given than number 
+    // of levels, extraneous values will be ignored.  If less are give, then
+    // values that correspond to individual levels will apply to those 
+    // levels.  Missing values will be taken from those for the finest
+    // level specified.
+    //
+    // ratio_to_coarser {
+    //   level_1 -- (int array) ratio between index spaces on 
+    //              level 1 to level 0 [REQD]
+    //   level_2 -- (int array)  ratio between index spaces on 
+    //              level 2 to level 1 [REQD]
+    //   etc....
+    // }
+    // largest_patch_size {
+    //   level_0 -- (int array) largest patch allowed on level 0. 
+    //              [REQD]    
+    //   level_1 -- (int array)    "       "      "   "  level 1 
+    //              [level 0 entry]
+    //   etc....                       
+    // }
+    max_levels = 6
+    proper_nesting_buffer = 2, 2, 2, 2, 2, 2
+    ratio_to_coarser {
+        level_1            = 2, 2, 2
+        level_2            = 2, 2, 2
+        level_3            = 2, 2, 2
+        level_4            = 2, 2, 2
+    }
+    largest_patch_size {
+        // level_0 = 32, 32
+        // level_0 = 8, 8
+        level_0 = -1, -1, -1
+        // all finer levels will use same values as level_0...
+    }
+}
+
+GriddingAlgorithm {
+    enforce_proper_nesting = TRUE
+    extend_to_domain_boundary = FALSE
+    proper_nesting_buffer = 2, 2, 2, 2, 2, 2
+    // load_balance = FALSE
+    efficiency_tolerance = 0.80
+    combine_efficiency = 0.75
+    // write_regrid_boxes = TRUE
+    // read_regrid_boxes = TRUE
+    // regrid_boxes_filename = "grid"
+    check_nonrefined_tags = "ERROR"
+    check_overlapping_patches = "ERROR"
+    extend_tags_to_bdry = TRUE
+    sequentialize_patch_indices = TRUE
+    barrier_before_regrid = TRUE
+    barrier_before_find_refinement = TRUE
+    barrier_before_cluster = TRUE
+    barrier_before_nest = TRUE
+    barrier_before_limit = TRUE
+    barrier_before_extend = TRUE
+    barrier_before_balance = TRUE
+    barrier_after_find_refinement = TRUE
+    coalesce_boxes = FALSE
+}
diff -r 2816cd6f8030 -r c77b196abc8c input/sinker.input
--- a/input/sinker.input	Wed Jun 06 07:43:07 2012 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,234 +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:   Input file for example FAC Stokes solver 
- *
- ************************************************************************/
-// This is the input file for the 2D FAC example
-// demonstrating changes in boundary conditions.
-//
-// Note that using constant refine prolongation
-// lead to slower convergence.
-
-Main {
-    dim = 2
-    // Base name for output files.
-    base_name = "sinker"
-    // Whether to log all nodes in a parallel run.
-    log_all_nodes = TRUE
-    // Visualization writers to write files for.
-    vis_writer = "Vizamrai", "VisIt"
-}
-
-Stokes {
-    // The FACStokes class is the "user class" in this example.
-    // It owns the solver and contains the code to set up the solver.
-    // The inputs for FACStokes is simply the inputs for the individual
-    // parts owned by the FACStokes class.
-    adaption_threshold = 1.0e-3
-    min_full_refinement_level = 1
-
-    viscosity_ijk= 11, 11
-    viscosity_coord_min= -0.001, -0.001
-    viscosity_coord_max= 1.001, 1.001
-    viscosity_data= 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1e2, 1e2, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1e2, 1e2, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
-
-    v_rhs_ijk= 11, 11
-    v_rhs_coord_min= -0.001, -0.001
-    v_rhs_coord_max= 1.001, 1.001
-    // v_rhs_data= 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1.03, 1.03, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1.03, 1.03, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
-
-    v_rhs_data= 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0.03, 0.03, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0.03, 0.03, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-
-    // p_initial_ijk= 2, 2
-    // p_initial_coord_min= 0, 0
-    // p_initial_coord_max= 1, 1
-    // p_initial_data= 1,1,0,0
-
-    fac_solver {
-        // This is the input for the cell-centered Stokes FAC solver
-        // class in the SAMRAI library.
-        enable_logging = TRUE   // Bool flag to switch logging on/off
-        max_cycles = 100         // Max number of FAC cycles to use
-        residual_tol = 1e-3     // Residual tolerance to solve for
-        num_pre_sweeps = 8      // Number of presmoothing sweeps to use
-        num_post_sweeps = 8     // Number of postsmoothing sweeps to use
-        smoothing_choice = "Tackley"
-        coarse_solver_choice = "Tackley"
-        // smoothing_choice = "Gerya"
-        // coarse_solver_choice = "Gerya"
-        coarse_solver_max_iterations = 32
-        coarse_solver_tolerance = 1e-5
-        // p_prolongation_method = "P_MDPI_REFINE"
-        p_prolongation_method = "P_REFINE"
-        v_prolongation_method = "V_REFINE"
-        p_rrestriction_method = "RESID_COARSEN"
-    }
-    bc_coefs {
-        // These are the boundary condition specifications.  The number
-        // after "boundary_" is the location index of the boundary.
-        // The inputs are arrays of strings where the first string
-        // indicates the type of values you want to set.  "slope" means
-        // boundary slope, "value" means boundary value, and "coefficients"
-        // mean the raw Robin boundary condition coefficients.
-        // The remaining strings are converted into numbers as
-        // appropriate for what boundary condition you specified with
-        // the first string.  Other boundary conditions are possible.
-        // see the solv_RobinBcCoefStrategy class.
-        // Examples:
-        // boundary_0 = "slope", "0"
-        // boundary_1 = "coefficients", "0", "0"
-        // boundary_2 = "value", "0"
-        // boundary_3 = "value", "0"
-        boundary_0 = "value", "0"
-        boundary_1 = "value", "0"
-        boundary_2 = "value", "0"
-        boundary_3 = "value", "0"
-    }
-}
-
-CartesianGridGeometry {
-    //  Specify lower/upper corners of the computational domain and a
-    //  set of non-overlapping boxes defining domain interior.  If union 
-    //  of boxes is not a parallelpiped, lower/upper corner data corresponds 
-    //  to min/max corner indices over all boxes given.
-    //  x_lo  -- (double array) lower corner of computational domain [REQD]
-    //  x_up  -- (double array) upper corner of computational domain [REQD]
-    //  domain_boxes  -- (box array) set of boxes that define interior of 
-    //                   physical domain. [REQD]
-    //  periodic_dimension -- (int array) coordinate directions in which 
-    //                        domain is periodic.  Zero indicates not
-    //                        periodic, non-zero value indicates periodicity.
-    //                        [0]
-    // domain_boxes = [(0,0), (15,15)]
-    domain_boxes = [(0,0), (3,3)]
-    x_lo         = 0, 0
-    x_up         = 1, 1
-}
-
-StandardTagAndInitialize {
-    tagging_method = "GRADIENT_DETECTOR"
-}
-
-PatchHierarchy {
-    // Information used to create patches in AMR hierarchy.
-    // max_levels -- (int) max number of mesh levels in hierarchy [REQD]
-    // 
-    // For most of the following parameters, the number of precribed data
-    // values need not match the number of levels in the hierarchy 
-    // (determined by max_levels).  If more values are given than number 
-    // of levels, extraneous values will be ignored.  If less are give, then
-    // values that correspond to individual levels will apply to those 
-    // levels.  Missing values will be taken from those for the finest
-    // level specified.
-    //
-    // ratio_to_coarser {
-    //   level_1 -- (int array) ratio between index spaces on 
-    //              level 1 to level 0 [REQD]
-    //   level_2 -- (int array)  ratio between index spaces on 
-    //              level 2 to level 1 [REQD]
-    //   etc....
-    // }
-    // largest_patch_size {
-    //   level_0 -- (int array) largest patch allowed on level 0. 
-    //              [REQD]    
-    //   level_1 -- (int array)    "       "      "   "  level 1 
-    //              [level 0 entry]
-    //   etc....                       
-    // }
-    max_levels = 5
-    proper_nesting_buffer = 2, 2, 2, 2, 2, 2
-    ratio_to_coarser {
-        level_1            = 2, 2
-        level_2            = 2, 2
-        level_3            = 2, 2
-        level_4            = 2, 2
-    }
-    largest_patch_size {
-        // level_0 = 32, 32
-        // level_0 = 8, 8
-        level_0 = -1, -1
-        // all finer levels will use same values as level_0...
-    }
-}
-
-GriddingAlgorithm {
-    enforce_proper_nesting = TRUE
-    extend_to_domain_boundary = FALSE
-    proper_nesting_buffer = 2, 2, 2, 2, 2, 2
-    // load_balance = FALSE
-    efficiency_tolerance = 0.80
-    combine_efficiency = 0.75
-    // write_regrid_boxes = TRUE
-    // read_regrid_boxes = TRUE
-    // regrid_boxes_filename = "grid"
-    check_nonrefined_tags = "ERROR"
-    check_overlapping_patches = "ERROR"
-    extend_tags_to_bdry = TRUE
-    sequentialize_patch_indices = TRUE
-    barrier_before_regrid = TRUE
-    barrier_before_find_refinement = TRUE
-    barrier_before_cluster = TRUE
-    barrier_before_nest = TRUE
-    barrier_before_limit = TRUE
-    barrier_before_extend = TRUE
-    barrier_before_balance = TRUE
-    barrier_after_find_refinement = TRUE
-    coalesce_boxes = FALSE
-}
diff -r 2816cd6f8030 -r c77b196abc8c input/sinker3D.input
--- a/input/sinker3D.input	Wed Jun 06 07:43:07 2012 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1099 +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:   Input file for example FAC Stokes solver 
- *
- ************************************************************************/
-// This is the input file for the 2D FAC example
-// demonstrating changes in boundary conditions.
-//
-// Note that using constant refine prolongation
-// lead to slower convergence.
-
-Main {
-    dim = 3
-    // Base name for output files.
-    base_name = "sinker3D"
-    // Whether to log all nodes in a parallel run.
-    log_all_nodes = TRUE
-    // Visualization writers to write files for.
-    vis_writer = "Vizamrai", "VisIt"
-}
-
-Stokes {
-    // The FACStokes class is the "user class" in this example.
-    // It owns the solver and contains the code to set up the solver.
-    // The inputs for FACStokes is simply the inputs for the individual
-    // parts owned by the FACStokes class.
-    adaption_threshold = 1.0e-3
-    min_full_refinement_level = 1
-
-    viscosity_ijk= 11, 11, 11
-    viscosity_coord_min= -0.001, -0.001, -0.001
-    viscosity_coord_max= 1.001, 1.001, 1.001
-    viscosity_data= 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1e2, 1e2, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1e2, 1e2, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1e2, 1e2, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1e2, 1e2, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
-
-    v_rhs_ijk= 11, 11, 11
-    v_rhs_coord_min= -0.001, -0.001, -0.001
-    v_rhs_coord_max= 1.001, 1.001, 1.001
-    v_rhs_data= 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0.03, 0.03, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0.03, 0.03, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0.03, 0.03, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0.03, 0.03, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-
-    // v_rhs_data= 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1.03, 1.03, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1.03, 1.03, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1.03, 1.03, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1.03, 1.03, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-
-    // p_initial_ijk= 2, 2, 2
-    // p_initial_coord_min= 0, 0, 0
-    // p_initial_coord_max= 1, 1, 1
-    // p_initial_data= 1,1,0,0, 1,1,0,0
-
-    fac_solver {
-        // This is the input for the cell-centered Stokes FAC solver
-        // class in the SAMRAI library.
-        enable_logging = TRUE   // Bool flag to switch logging on/off
-        max_cycles = 100         // Max number of FAC cycles to use
-        residual_tol = 1e-6     // Residual tolerance to solve for
-        num_pre_sweeps = 16      // Number of presmoothing sweeps to use
-        num_post_sweeps = 16     // Number of postsmoothing sweeps to use
-        smoothing_choice = "Tackley"
-        coarse_solver_choice = "Tackley"
-        // smoothing_choice = "Gerya"
-        // coarse_solver_choice = "Gerya"
-        coarse_solver_max_iterations = 32
-        coarse_solver_tolerance = 1e-12
-        // p_prolongation_method = "P_MDPI_REFINE"
-        p_prolongation_method = "P_REFINE"
-        v_prolongation_method = "V_REFINE"
-        p_rrestriction_method = "RESID_COARSEN"
-    }
-    bc_coefs {
-        // These are the boundary condition specifications.  The number
-        // after "boundary_" is the location index of the boundary.
-        // The inputs are arrays of strings where the first string
-        // indicates the type of values you want to set.  "slope" means
-        // boundary slope, "value" means boundary value, and "coefficients"
-        // mean the raw Robin boundary condition coefficients.
-        // The remaining strings are converted into numbers as
-        // appropriate for what boundary condition you specified with
-        // the first string.  Other boundary conditions are possible.
-        // see the solv_RobinBcCoefStrategy class.
-        // Examples:
-        // boundary_0 = "slope", "0"
-        // boundary_1 = "coefficients", "0", "0"
-        // boundary_2 = "value", "0"
-        // boundary_3 = "value", "0"
-        boundary_0 = "value", "0"
-        boundary_1 = "value", "0"
-        boundary_2 = "value", "0"
-        boundary_3 = "value", "0"
-    }
-}
-
-CartesianGridGeometry {
-    //  Specify lower/upper corners of the computational domain and a
-    //  set of non-overlapping boxes defining domain interior.  If union 
-    //  of boxes is not a parallelpiped, lower/upper corner data corresponds 
-    //  to min/max corner indices over all boxes given.
-    //  x_lo  -- (double array) lower corner of computational domain [REQD]
-    //  x_up  -- (double array) upper corner of computational domain [REQD]
-    //  domain_boxes  -- (box array) set of boxes that define interior of 
-    //                   physical domain. [REQD]
-    //  periodic_dimension -- (int array) coordinate directions in which 
-    //                        domain is periodic.  Zero indicates not
-    //                        periodic, non-zero value indicates periodicity.
-    //                        [0]
-    // domain_boxes = [(0,0), (15,15)]
-    domain_boxes = [(0,0,0), (3,3,3)]
-    x_lo         = 0, 0, 0
-    x_up         = 1, 1, 1
-}
-
-StandardTagAndInitialize {
-    tagging_method = "GRADIENT_DETECTOR"
-}
-
-PatchHierarchy {
-    // Information used to create patches in AMR hierarchy.
-    // max_levels -- (int) max number of mesh levels in hierarchy [REQD]
-    // 
-    // For most of the following parameters, the number of precribed data
-    // values need not match the number of levels in the hierarchy 
-    // (determined by max_levels).  If more values are given than number 
-    // of levels, extraneous values will be ignored.  If less are give, then
-    // values that correspond to individual levels will apply to those 
-    // levels.  Missing values will be taken from those for the finest
-    // level specified.
-    //
-    // ratio_to_coarser {
-    //   level_1 -- (int array) ratio between index spaces on 
-    //              level 1 to level 0 [REQD]
-    //   level_2 -- (int array)  ratio between index spaces on 
-    //              level 2 to level 1 [REQD]
-    //   etc....
-    // }
-    // largest_patch_size {
-    //   level_0 -- (int array) largest patch allowed on level 0. 
-    //              [REQD]    
-    //   level_1 -- (int array)    "       "      "   "  level 1 
-    //              [level 0 entry]
-    //   etc....                       
-    // }
-    max_levels = 5
-    proper_nesting_buffer = 2, 2, 2, 2, 2, 2
-    ratio_to_coarser {
-        level_1            = 2, 2, 2
-        level_2            = 2, 2, 2
-        level_3            = 2, 2, 2
-        level_4            = 2, 2, 2
-    }
-    largest_patch_size {
-        // level_0 = 32, 32
-        // level_0 = 8, 8
-        level_0 = -1, -1, -1
-        // all finer levels will use same values as level_0...
-    }
-}
-
-GriddingAlgorithm {
-    enforce_proper_nesting = TRUE
-    extend_to_domain_boundary = FALSE
-    proper_nesting_buffer = 2, 2, 2, 2, 2, 2
-    // load_balance = FALSE
-    efficiency_tolerance = 0.80
-    combine_efficiency = 0.75
-    // write_regrid_boxes = TRUE
-    // read_regrid_boxes = TRUE
-    // regrid_boxes_filename = "grid"
-    check_nonrefined_tags = "ERROR"
-    check_overlapping_patches = "ERROR"
-    extend_tags_to_bdry = TRUE
-    sequentialize_patch_indices = TRUE
-    barrier_before_regrid = TRUE
-    barrier_before_find_refinement = TRUE
-    barrier_before_cluster = TRUE
-    barrier_before_nest = TRUE
-    barrier_before_limit = TRUE
-    barrier_before_extend = TRUE
-    barrier_before_balance = TRUE
-    barrier_after_find_refinement = TRUE
-    coalesce_boxes = FALSE
-}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FAC.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FAC.h	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,209 @@
+/*************************************************************************
+ *
+ * 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:   Numerical routines for example FAC Elastic solver 
+ *
+ ************************************************************************/
+#ifndef GAMRA_ELASTIC_FAC_H
+#define GAMRA_ELASTIC_FAC_H
+
+#include "Elastic/FACSolver.h"
+#include "SAMRAI/pdat/CellVariable.h"
+#include "SAMRAI/tbox/Database.h"
+#include "SAMRAI/hier/Box.h"
+#include "SAMRAI/solv/LocationIndexRobinBcCoefs.h"
+#include "SAMRAI/hier/Patch.h"
+#include "SAMRAI/hier/PatchHierarchy.h"
+#include "SAMRAI/hier/PatchLevel.h"
+#include "SAMRAI/tbox/Pointer.h"
+#include "SAMRAI/pdat/SideVariable.h"
+#include "SAMRAI/mesh/StandardTagAndInitStrategy.h"
+#include "SAMRAI/hier/VariableContext.h"
+#include "SAMRAI/appu/VisDerivedDataStrategy.h"
+#include "SAMRAI/appu/VisItDataWriter.h"
+
+namespace SAMRAI {
+namespace Elastic {
+  /*!
+   * @brief Class to solve a sample Elastic equation on a SAMR grid.
+   */
+  class FAC:
+    public mesh::StandardTagAndInitStrategy,
+    public appu::VisDerivedDataStrategy
+  {
+
+  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 (may be NULL)
+     */
+    FAC(const std::string& object_name,
+        const tbox::Dimension& dim,
+        tbox::Pointer<tbox::Database> database =
+        tbox::Pointer<tbox::Database>(NULL));
+
+    virtual ~FAC() {}
+
+    //@{ @name mesh::StandardTagAndInitStrategy virtuals
+
+    /*!
+     * @brief Allocate and initialize data for a new level
+     * in the patch hierarchy.
+     *
+     * This is where you implement the code for initialize data on
+     * the grid.  All the information needed to initialize the grid
+     * are in the arguments.
+     *
+     * @see mesh::StandardTagAndInitStrategy::initializeLevelData()
+     */
+    virtual void
+    initializeLevelData(const tbox::Pointer<hier::BasePatchHierarchy> hierarchy,
+                        const int level_number,
+                        const double init_data_time,
+                        const bool can_be_refined,
+                        const bool initial_time,
+                        const tbox::Pointer<hier::BasePatchLevel> old_level,
+                        const bool allocate_data);
+
+    /*!
+     * @brief Reset any internal hierarchy-dependent information.
+     */
+    virtual void
+    resetHierarchyConfiguration(tbox::Pointer<hier::BasePatchHierarchy> new_hierarchy,
+                                int coarsest_level,
+                                int finest_level);
+
+    //@}
+
+    virtual void
+    applyGradientDetector(const tbox::Pointer<hier::BasePatchHierarchy> hierarchy,
+                          const int level_number,
+                          const double error_data_time,
+                          const int tag_index,
+                          const bool initial_time,
+                          const bool uses_richardson_extrapolation);
+
+    void computeAdaptionEstimate(pdat::CellData<double>& estimate_data,
+                                 const pdat::CellData<double>& soln_cell_data)
+      const;
+
+    //@{ @name appu::VisDerivedDataStrategy virtuals
+
+    virtual bool
+    packDerivedDataIntoDoubleBuffer(double* buffer,
+                                    const hier::Patch& patch,
+                                    const hier::Box& region,
+                                    const std::string& variable_name,
+                                    int depth_id) const;
+
+    //@}
+
+    /*!
+     * @brief Solve using HYPRE Elastic solver
+     *
+     * Set up the linear algebra problem and use a
+     * solv::Elastic::FACSolver object to solve it.
+     * -# Set initial guess
+     * -# Set boundary conditions
+     * -# Specify Elastic equation parameters
+     * -# Call solver
+     */
+    int
+    solve();
+
+#ifdef HAVE_HDF5
+    /*!
+     * @brief Set up external plotter to plot internal
+     * data from this class.
+     *
+     * After calling this function, the external
+     * data writer may be used to write the
+     * viz file for this object.
+     *
+     * The internal hierarchy is used and must be
+     * established before calling this function.
+     * (This is commonly done by building a hierarchy
+     * with the mesh::StandardTagAndInitStrategy virtual
+     * functions implemented by this class.)
+     *
+     * @param viz_writer VisIt writer
+     */
+    int
+    setupPlotter(appu::VisItDataWriter& plotter) const;
+#endif
+
+  private:
+    void fix_moduli();
+    std::string d_object_name;
+
+    const tbox::Dimension d_dim;
+
+    tbox::Pointer<hier::PatchHierarchy> d_hierarchy;
+
+    //@{
+    /*!
+     * @name Major algorithm objects.
+     */
+
+    /*!
+     * @brief FAC Elastic solver.
+     */
+    solv::Elastic::FACSolver d_elastic_fac_solver;
+
+    /*!
+     * @brief Boundary condition coefficient implementation.
+     */
+    solv::LocationIndexRobinBcCoefs d_bc_coefs;
+
+    //@}
+
+    //@{
+
+    /*!
+     * @name Private state variables for solution.
+     */
+
+    /*!
+     * @brief Context owned by this object.
+     */
+    tbox::Pointer<hier::VariableContext> d_context;
+  
+    /*!
+     * @brief Descriptor indices of internal data.
+     *
+     * These are initialized in the constructor and never change.
+     */
+
+    double d_adaption_threshold;
+    int min_full_refinement_level;
+  public:
+    int p_id, cell_moduli_id, edge_moduli_id, dp_id, p_exact_id,
+      p_rhs_id, v_id, v_rhs_id;
+
+    tbox::Array<double> lambda, lambda_xyz_max, lambda_xyz_min;
+    tbox::Array<int> lambda_ijk;
+
+    tbox::Array<double> mu, mu_xyz_max, mu_xyz_min;
+    tbox::Array<int> mu_ijk;
+
+    tbox::Array<double> v_rhs, v_rhs_xyz_max, v_rhs_xyz_min;
+    tbox::Array<int> v_rhs_ijk;
+
+    tbox::Array<double> p_initial, p_initial_xyz_max, p_initial_xyz_min;
+    tbox::Array<int> p_initial_ijk;
+    //@}
+
+  };
+
+}
+}
+
+#endif  // included_FACElastic
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FAC/FAC.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FAC/FAC.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,226 @@
+/*************************************************************************
+ *
+ * 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:   Numerical routines for example FAC Elastic solver 
+ *
+ ************************************************************************/
+#include "Elastic/FAC.h"
+
+#include "SAMRAI/hier/IntVector.h"
+#include "SAMRAI/geom/CartesianGridGeometry.h"
+#include "SAMRAI/geom/CartesianPatchGeometry.h"
+#include "SAMRAI/solv/SimpleCellRobinBcCoefs.h"
+#include "SAMRAI/pdat/CellData.h"
+#include "SAMRAI/math/HierarchyCellDataOpsReal.h"
+#include "SAMRAI/pdat/SideData.h"
+#include "SAMRAI/tbox/Utilities.h"
+#include "SAMRAI/hier/Variable.h"
+#include "SAMRAI/hier/VariableDatabase.h"
+
+namespace SAMRAI {
+
+  namespace Elastic {
+    /* A little utility routine to validate the sizes of input arrays */
+    void check_array_sizes(const tbox::Array<int> ijk,
+                           const tbox::Array<double> min,
+                           const tbox::Array<double> max,
+                           const tbox::Array<double> data,
+                           const int dim, const std::string &name,
+                           const int num_components=1)
+    {
+      if(ijk.size()!=dim)
+        TBOX_ERROR("Bad number of elements in " << name << "_ijk.  Expected "
+                   << dim << " but got " << ijk.size());
+      if(min.size()!=dim)
+        TBOX_ERROR("Bad number of elements in "
+                   << name << "_coord_min.  Expected "
+                   << dim << " but got " << min.size());
+      if(max.size()!=dim)
+        TBOX_ERROR("Bad number of elements in "
+                   << name << "_coord_max.  Expected "
+                   << dim << " but got " << max.size());
+      int data_size(1);
+      for(int d=0; d<dim; ++d)
+        data_size*=ijk[d];
+      if(data.size()!=data_size*num_components)
+        TBOX_ERROR("Bad number of elements in "
+                   << name << "_data.  Expected "
+                   << data_size << " but got " << data.size());
+    }
+  }
+  /*
+*************************************************************************
+* Constructor creates a unique context for the object and register      *
+* all its internal variables with the variable database.                *
+*************************************************************************
+*/
+  Elastic::FAC::FAC(const std::string& object_name,
+                    const tbox::Dimension& dimension,
+                    tbox::Pointer<tbox::Database> database):
+    d_object_name(object_name),
+    d_dim(dimension),
+    d_hierarchy(NULL),
+    d_elastic_fac_solver((d_dim),
+                         object_name + "::elastic_hypre",
+                         (!database.isNull() &&
+                          database->isDatabase("fac_solver")) ?
+                         database->getDatabase("fac_solver"):
+                         tbox::Pointer<tbox::Database>(NULL)),
+    d_bc_coefs(d_dim,
+               object_name + "::bc_coefs",
+               (!database.isNull() &&
+                database->isDatabase("bc_coefs")) ?
+               database->getDatabase("bc_coefs"):
+               tbox::Pointer<tbox::Database>(NULL)),
+    d_context()
+  {
+    const int dim(d_dim.getValue());
+    hier::VariableDatabase* vdb =
+      hier::VariableDatabase::getDatabase();
+
+    /*
+     * Get a unique context for variables owned by this object.
+     */
+    d_context = vdb->getContext(d_object_name + ":Context");
+
+    /*
+     * Register variables with hier::VariableDatabase
+     * and get the descriptor indices for those variables.
+     */
+
+    tbox::Pointer<pdat::CellVariable<double> >
+      p_ptr(new pdat::CellVariable<double>(d_dim, object_name + ":p", 1));
+    p_id = vdb->registerVariableAndContext(p_ptr, d_context,
+                                           hier::IntVector(d_dim, 1)
+                                           /* ghost cell width is 1 for
+                                              stencil widths */);
+
+	int depth=2;
+    tbox::Pointer<pdat::CellVariable<double> >
+      cell_moduli_ptr(new pdat::CellVariable<double>(d_dim,
+                                                        object_name
+                                                        + ":cell_moduli",depth));
+    cell_moduli_id = vdb->registerVariableAndContext(cell_moduli_ptr,
+                                                        d_context,
+                                                        hier::IntVector(d_dim, 1)
+                                                        /* ghost cell width is
+                                                           1 in case needed */);
+
+    if(dim==2)
+      {
+        tbox::Pointer<pdat::NodeVariable<double> >
+          edge_moduli_ptr(new pdat::NodeVariable<double>(d_dim,
+                                                            object_name
+                                                            + ":edge_moduli",depth));
+        edge_moduli_id =
+          vdb->registerVariableAndContext(edge_moduli_ptr,d_context,
+                                          hier::IntVector(d_dim,1)
+                                          /* ghost cell width is 1 in
+                                             case needed */);
+      }
+    else if(dim==3)
+      {
+        tbox::Pointer<pdat::EdgeVariable<double> >
+          edge_moduli_ptr(new pdat::EdgeVariable<double>(d_dim,
+                                                            object_name
+                                                            + ":edge_moduli",depth));
+        edge_moduli_id =
+          vdb->registerVariableAndContext(edge_moduli_ptr,d_context,
+                                          hier::IntVector(d_dim,1)
+                                          /* ghost cell width is 1 in
+                                             case needed */);
+      }
+
+    tbox::Pointer<pdat::CellVariable<double> >
+      dp_ptr(new pdat::CellVariable<double>(d_dim, object_name + ":dp"));
+    dp_id = vdb->registerVariableAndContext(dp_ptr,d_context,
+                                            hier::IntVector(d_dim, 1)
+                                            /* ghost cell width is
+                                                    1 in case needed */);
+
+    tbox::Pointer<pdat::CellVariable<double> >
+      p_exact_ptr(new pdat::CellVariable<double>(d_dim, object_name + ":p exact"));
+    p_exact_id = vdb->registerVariableAndContext(p_exact_ptr,d_context,
+                                                 hier::IntVector(d_dim, 1)
+                                                 /* ghost cell width is
+                                                    1 in case needed */);
+
+    tbox::Pointer<pdat::CellVariable<double> >
+      p_rhs_ptr(new pdat::CellVariable<double>(d_dim,object_name
+                                               + ":p right hand side"));
+    p_rhs_id = vdb->registerVariableAndContext(p_rhs_ptr,d_context,
+                                               hier::IntVector(d_dim, 1));
+
+    tbox::Pointer<pdat::SideVariable<double> >
+      v_ptr(new pdat::SideVariable<double>(d_dim, object_name + ":v", 1));
+    v_id = vdb->registerVariableAndContext(v_ptr, d_context,
+                                           hier::IntVector(d_dim, 1)
+                                           /* ghost cell width is 1 for
+                                              stencil widths */);
+
+    tbox::Pointer<pdat::SideVariable<double> >
+      v_rhs_ptr(new pdat::SideVariable<double>(d_dim,object_name
+                                               + ":v right hand side"));
+    v_rhs_id = vdb->registerVariableAndContext(v_rhs_ptr,d_context,
+                                               hier::IntVector(d_dim, 1)
+                                               /* ghost cell width is
+                                                  1 for coarsening
+                                                  operator */);
+
+    d_adaption_threshold=database->getDoubleWithDefault("adaption_threshold",
+                                                        1.0e-15);
+    min_full_refinement_level
+      =database->getIntegerWithDefault("min_full_refinement_level",0);
+
+    if(database->keyExists("lambda_data"))
+      {
+        lambda_ijk=database->getIntegerArray("lambda_ijk");
+        lambda_xyz_min=database->getDoubleArray("lambda_coord_min");
+        lambda_xyz_max=database->getDoubleArray("lambda_coord_max");
+        lambda=database->getDoubleArray("lambda_data");
+        check_array_sizes(lambda_ijk,lambda_xyz_min,lambda_xyz_max,
+                          lambda,dim,"lambda");
+      }
+
+    if(database->keyExists("mu_data"))
+      {
+        mu_ijk=database->getIntegerArray("mu_ijk");
+        mu_xyz_min=database->getDoubleArray("mu_coord_min");
+        mu_xyz_max=database->getDoubleArray("mu_coord_max");
+        mu=database->getDoubleArray("mu_data");
+        check_array_sizes(mu_ijk,mu_xyz_min,mu_xyz_max,
+                          mu,dim,"mu");
+      }
+
+    if(database->keyExists("v_rhs_data"))
+      {
+        v_rhs_ijk=database->getIntegerArray("v_rhs_ijk");
+        v_rhs_xyz_min=database->getDoubleArray("v_rhs_coord_min");
+        v_rhs_xyz_max=database->getDoubleArray("v_rhs_coord_max");
+        v_rhs=database->getDoubleArray("v_rhs_data");
+        check_array_sizes(v_rhs_ijk,v_rhs_xyz_min,v_rhs_xyz_max,
+                          v_rhs,dim,"v_rhs",dim);
+      }
+
+    if(database->keyExists("p_initial_data"))
+      {
+        p_initial_ijk=database->getIntegerArray("p_initial_ijk");
+        p_initial_xyz_min=database->getDoubleArray("p_initial_coord_min");
+        p_initial_xyz_max=database->getDoubleArray("p_initial_coord_max");
+        p_initial=database->getDoubleArray("p_initial_data");
+        check_array_sizes(p_initial_ijk,p_initial_xyz_min,p_initial_xyz_max,
+                          p_initial,dim,"p_initial");
+      }
+
+    /*
+     * Specify an implementation of solv::RobinBcCoefStrategy for the
+     * solver to use.  We use the implementation
+     * solv::LocationIndexRobinBcCoefs, but other implementations are
+     * possible, including user-implemented.
+     */
+    d_elastic_fac_solver.setBcObject(&d_bc_coefs);
+  }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FAC/applyGradientDetector.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FAC/applyGradientDetector.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,113 @@
+#include "Elastic/FAC.h"
+#include "SAMRAI/geom/CartesianGridGeometry.h"
+#include "SAMRAI/pdat/MDA_Access.h"
+#include "SAMRAI/pdat/ArrayDataAccess.h"
+
+void SAMRAI::Elastic::FAC::applyGradientDetector
+(const tbox::Pointer<hier::BasePatchHierarchy> hierarchy_,
+ const int ln,
+ const double ,
+ const int tag_index,
+ const bool ,
+ const bool )
+{
+  const tbox::Pointer<hier::PatchHierarchy> hierarchy__ = hierarchy_;
+  hier::PatchHierarchy& hierarchy = *hierarchy__;
+  hier::PatchLevel& level =
+    (hier::PatchLevel &) * hierarchy.getPatchLevel(ln);
+  
+  int ntag = 0, ntotal = 0;
+  double maxestimate = 0;
+  for(hier::PatchLevel::Iterator pi(level); pi; pi++)
+    {
+      hier::Patch& patch = **pi;
+      tbox::Pointer<hier::PatchData>
+        tag_data = patch.getPatchData(tag_index);
+      ntotal += patch.getBox().numberCells().getProduct();
+      if (tag_data.isNull())
+        {
+          TBOX_ERROR("Data index "
+                     << tag_index << " does not exist for patch.\n");
+        }
+      tbox::Pointer<pdat::CellData<int> > tag_cell_data_ = tag_data;
+      if (tag_cell_data_.isNull())
+        {
+          TBOX_ERROR("Data index " << tag_index << " is not cell int data.\n");
+        }
+      tbox::Pointer<hier::PatchData> soln_data = patch.getPatchData(v_id);
+      if (soln_data.isNull())
+        {
+          TBOX_ERROR("Data index " << v_id << " does not exist for patch.\n");
+        }
+      tbox::Pointer<pdat::SideData<double> > soln_side_data_ = soln_data;
+      if (soln_side_data_.isNull())
+        {
+          TBOX_ERROR("Data index " << v_id << " is not side data.\n");
+        }
+      pdat::SideData<double>& v = *soln_side_data_;
+      pdat::CellData<int>& tag_cell_data = *tag_cell_data_;
+                              
+      tbox::Pointer<geom::CartesianPatchGeometry> geom = patch.getPatchGeometry();
+
+      tag_cell_data.fill(0);
+      for (pdat::CellIterator ci(patch.getBox()); ci; ci++)
+        {
+          const pdat::CellIndex cell_index(*ci);
+
+	  double curve(0.);
+	  for (int ix=0; ix<d_dim.getValue(); ++ix)
+	  {
+            const pdat::SideIndex x(cell_index,ix,pdat::SideIndex::Lower);
+	    for (int d=0; d<d_dim.getValue(); ++d){
+		    hier::Index ip(d_dim,0),
+			        jp(d_dim,0),
+			        kp(d_dim,0);
+		    ip(0)=1;
+		    jp(1)=1;
+		    if (3==d_dim.getValue())
+		    {
+			kp(2)=1;
+		    }
+              const hier::Index pp[]={ip,jp,kp};
+
+              if(cell_index[ix]==patch.getBox().lower(ix)
+                 && geom->getTouchesRegularBoundary(ix,0))
+	      {
+	      curve=std::max(curve,std::abs(v(x+pp[ix]+pp[ix])-2*v(x+pp[ix])+v(x)));
+	      } else if(cell_index[ix]==patch.getBox().upper(ix)
+                 && geom->getTouchesRegularBoundary(ix,1))
+	      {
+	      curve=std::max(curve,std::abs(v(x+pp[ix])-2*v(x)+v(x-pp[ix])));
+	      }
+	      else
+	      {
+	      curve=std::max(curve,std::abs(v(x+pp[ix]+pp[ix])-v(x+pp[ix])-v(x)+v(x-pp[ix])));
+	      }
+	    }
+	  }
+          /*
+	   * tbox::plog << "estimate "
+                     << cell_index << " "
+                     << d_adaption_threshold << " "
+                     << curve << " "
+                     << std::boolalpha
+                     << (curve > d_adaption_threshold)
+                     << " "
+                     << "\n";
+		     */
+
+          if (maxestimate < curve)
+               maxestimate=curve;
+          if (curve > d_adaption_threshold || ln<min_full_refinement_level)
+            {
+              tag_cell_data(cell_index) = 1;
+              ++ntag;
+            }
+        }
+    }
+  tbox::plog << "Adaption threshold is " << d_adaption_threshold << "\n";
+  tbox::plog << "Number of cells tagged on level " << ln << " is "
+             << ntag << "/" << ntotal << "\n";
+  tbox::plog << "Max estimate is " << maxestimate << "\n";
+}
+
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FAC/fix_moduli.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FAC/fix_moduli.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,141 @@
+#include "Elastic/FAC.h"
+#include "SAMRAI/geom/CartesianGridGeometry.h"
+
+/* Fix the moduli on the coarse grids by coarsening from the finer
+   grids. */
+
+void SAMRAI::Elastic::FAC::fix_moduli()
+{
+  const int ln_max(d_hierarchy->getFinestLevelNumber());
+
+  tbox::Pointer<xfer::CoarsenOperator> cell_moduli_coarsen_operator;
+  tbox::Pointer<xfer::CoarsenAlgorithm> cell_moduli_coarsen_algorithm;
+  tbox::Array<tbox::Pointer<xfer::CoarsenSchedule> >
+    cell_moduli_coarsen_schedules;
+
+  hier::VariableDatabase* vdb = hier::VariableDatabase::getDatabase();
+  tbox::Pointer<geom::CartesianGridGeometry> geometry =
+    d_hierarchy->getGridGeometry();
+  tbox::Pointer<hier::Variable> variable;
+  vdb->mapIndexToVariable(cell_moduli_id, variable);
+  cell_moduli_coarsen_operator =
+    geometry->lookupCoarsenOperator(variable,
+                                    "CONSERVATIVE_COARSEN");
+                                    // "CELL_VISCOSITY_COARSEN");
+
+  if (!cell_moduli_coarsen_operator) {
+    TBOX_ERROR(d_object_name
+               << ": Cannot find cell moduli coarsening operator");
+  }
+
+  cell_moduli_coarsen_schedules.resizeArray(ln_max + 1);
+  cell_moduli_coarsen_algorithm = new xfer::CoarsenAlgorithm(d_dim);
+  cell_moduli_coarsen_algorithm->
+    registerCoarsen(cell_moduli_id,cell_moduli_id,
+                    cell_moduli_coarsen_operator);
+
+  for (int dest_ln = 0; dest_ln < ln_max; ++dest_ln) {
+    cell_moduli_coarsen_schedules[dest_ln] =
+      cell_moduli_coarsen_algorithm->
+      createSchedule(d_hierarchy->getPatchLevel(dest_ln),
+                     d_hierarchy->getPatchLevel(dest_ln + 1));
+    if (!cell_moduli_coarsen_schedules[dest_ln]) {
+      TBOX_ERROR(d_object_name
+                 << ": Cannot create a coarsen schedule for cell moduli restriction!\n");
+    }
+  }
+
+  for(int dest_ln=ln_max-1; dest_ln>=0; --dest_ln)
+    {
+      xfer::CoarsenAlgorithm coarsener(d_dim);
+      coarsener.registerCoarsen(cell_moduli_id, cell_moduli_id,
+                                cell_moduli_coarsen_operator);
+      coarsener.resetSchedule(cell_moduli_coarsen_schedules[dest_ln]);
+      cell_moduli_coarsen_schedules[dest_ln]->coarsenData();
+      cell_moduli_coarsen_algorithm->
+        resetSchedule(cell_moduli_coarsen_schedules[dest_ln]);
+    }
+
+  cell_moduli_coarsen_algorithm.setNull();
+  cell_moduli_coarsen_schedules.setNull();
+
+  /* Compute edge_moduli by averaging the cell moduli. */
+
+  hier::Index ip(hier::Index::getZeroIndex(d_dim)), jp(ip), kp(ip);
+  ip[0]=1;
+  jp[1]=1;
+  if(d_dim.getValue()>2)
+    kp[2]=1;
+  hier::Index pp[]={ip,jp,kp};
+
+  for (int ln = 0; ln <= d_hierarchy->getFinestLevelNumber(); ++ln)
+    {
+      tbox::Pointer<hier::PatchLevel> level = d_hierarchy->getPatchLevel(ln);
+      hier::PatchLevel::Iterator i_p(*level);
+      for ( ; i_p; i_p++)
+        {
+          tbox::Pointer<hier::Patch> patch = *i_p;
+          tbox::Pointer<pdat::CellData<double> >
+            cell_moduli_ptr = patch->getPatchData(cell_moduli_id);
+          pdat::CellData<double> &cell_moduli(*cell_moduli_ptr);
+          if(2==d_dim.getValue())
+            {
+              tbox::Pointer<pdat::NodeData<double> >
+                edge_moduli_ptr = patch->getPatchData(edge_moduli_id);
+              pdat::NodeData<double> &edge_moduli(*edge_moduli_ptr);
+
+              for(pdat::NodeIterator ni(edge_moduli.getBox()); ni; ni++)
+                {
+                  for (int m=0;m<2;++m)
+                    {
+                      pdat::NodeIndex e=ni();
+                      pdat::CellIndex c(e);
+                      cell_moduli(c,m);
+                      cell_moduli(c-ip,m);
+                      cell_moduli(c-jp,m);
+                      cell_moduli(c-ip-jp,m);
+                      edge_moduli(e,m)=
+                        pow(cell_moduli(c,m)*cell_moduli(c-ip,m)
+                            *cell_moduli(c-jp,m)*cell_moduli(c-ip-jp,m),0.25);
+                    }
+		}
+            }
+          else
+            {
+              tbox::Pointer<pdat::EdgeData<double> >
+                edge_moduli_ptr = patch->getPatchData(edge_moduli_id);
+              pdat::EdgeData<double> &edge_moduli(*edge_moduli_ptr);
+              for(int axis=0;axis<3;++axis)
+                {
+                  const int axis2((axis+1)%3), axis3((axis+2)%3);
+                  hier::Box pbox=patch->getBox();
+                  pbox.grow(axis,edge_moduli.getGhostCellWidth()[axis]);
+
+                  for(pdat::EdgeIterator ni(pbox,axis); ni; ni++)
+                    {
+                      pdat::EdgeIndex e=ni();
+                      pdat::CellIndex c(e);
+		      for (int m=0;m<2;++m)
+                        {
+                          edge_moduli(e,m)=
+                            pow(cell_moduli(c,m)*cell_moduli(c-pp[axis2],m)
+                                *cell_moduli(c-pp[axis3],m)
+                                *cell_moduli(c-pp[axis2]-pp[axis3],m),0.25);
+                        }
+                    }
+                }
+            }
+        }
+
+      /* Ghost fill */
+      xfer::RefineAlgorithm refiner(d_dim);
+      refiner.registerRefine(edge_moduli_id,edge_moduli_id,
+                             edge_moduli_id,
+                             tbox::Pointer<xfer::RefineOperator>(0));
+
+      tbox::Pointer<xfer::RefineSchedule> schedule=
+        refiner.createSchedule(d_hierarchy->getPatchLevel(ln));
+        
+      schedule->fillData(0.0,false);
+    }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FAC/initializeLevelData.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FAC/initializeLevelData.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,477 @@
+/*************************************************************************
+ *
+ * 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:   Numerical routines for example FAC Elastic solver 
+ *
+ ************************************************************************/
+#include "Elastic/FAC.h"
+#include "SAMRAI/geom/CartesianGridGeometry.h"
+#include "FTensor.hpp"
+
+bool intersect_fault(const int &dim,
+                     const FTensor::Tensor1<double,3> &c0,
+                     const FTensor::Tensor1<double,3> &c1,
+                     const double fault[])
+{
+  bool result(true);
+  for(int d=1;d<dim;++d)
+    {
+      double y((c1(d)*c0(0) -  c1(0)*c0(d))/(c1(0) - c0(0)));
+      result=result && (y<=fault[d-1]/2 && y>-fault[d-1]/2);
+    }
+  return result;
+}
+
+void rotate(double cstrike, double sstrike, double cdip, double sdip, 
+            double x1, double x2, double x3, 
+            double * x1s, double * x1i, double * x2s, double * x3s, double * x3i)
+{
+
+  double x2r(cstrike*x1-sstrike*x2);
+
+  (*x1s)= cdip*x2r-sdip*x3;
+  (*x1i)= cdip*x2r+sdip*x3;
+  (*x2s)= sstrike*x1+cstrike*x2;
+  (*x3s)= sdip*x2r+cdip*x3;
+  (*x3i)=-sdip*x2r+cdip*x3;
+
+}
+
+double gauss(double x, double sigma)
+{
+  const double pi2 = atan(1.0)*8;
+  return exp(-0.5*(x/sigma)*(x/sigma))/sqrt(pi2)/sigma;
+}
+
+double omega(double x, double beta)
+{
+  const double pi=4*atan(1);
+
+  if (fabs(x) <= (1-2*beta)/(1-beta)/2)
+    {
+      return 1;
+    }
+  else
+    {
+      if (fabs(x) < 1./(2.*(1.-beta)))
+        {
+          return pow(cos(pi*((1.-beta)*fabs(x)-0.5+beta)/(2.*beta)),2.);
+        }
+      else
+        {
+          return 0;
+        }
+    }
+}
+
+/*
+*************************************************************************
+* Initialize data on a level.                                           *
+*                                                                       *
+* Allocate the solution, exact solution and rhs memory.                 *
+* Fill the rhs and exact solution.                                      *
+*************************************************************************
+*/
+void SAMRAI::Elastic::FAC::initializeLevelData
+(const tbox::Pointer<hier::BasePatchHierarchy> patch_hierarchy,
+ const int level_number,
+ const double ,
+ const bool ,
+ const bool ,
+ const tbox::Pointer<hier::BasePatchLevel> ,
+ const bool allocate_data)
+{
+  tbox::Pointer<hier::PatchHierarchy> hierarchy = patch_hierarchy;
+  tbox::Pointer<geom::CartesianGridGeometry> grid_geom =
+    hierarchy->getGridGeometry();
+
+  tbox::Pointer<hier::PatchLevel> level =
+    hierarchy->getPatchLevel(level_number);
+  const int dim=d_dim.getValue();
+
+  if (allocate_data) {
+    level->allocatePatchData(p_id);
+    level->allocatePatchData(cell_moduli_id);
+    level->allocatePatchData(edge_moduli_id);
+    level->allocatePatchData(dp_id);
+    level->allocatePatchData(p_rhs_id);
+    level->allocatePatchData(p_exact_id);
+    level->allocatePatchData(v_id);
+    level->allocatePatchData(v_rhs_id);
+  }
+
+  /*
+   * Initialize data in all patches in the level.
+   */
+  hier::PatchLevel::Iterator p_i(*level);
+  for (p_i.initialize(*level); p_i; p_i++) {
+
+    tbox::Pointer<hier::Patch> patch = *p_i;
+    if (patch.isNull()) {
+      TBOX_ERROR(d_object_name
+                 << ": Cannot find patch.  Null patch pointer.");
+    }
+    tbox::Pointer<geom::CartesianPatchGeometry>
+      geom = patch->getPatchGeometry();
+    const double *dx=geom->getDx();
+
+    /* Initialize cell moduli */
+    tbox::Pointer<pdat::CellData<double> > cell_moduli =
+      patch->getPatchData(cell_moduli_id);
+
+    hier::Box cell_moduli_box = cell_moduli->getBox();
+
+    for(pdat::CellIterator ci(cell_moduli->getGhostBox()); ci; ci++)
+      {
+        pdat::CellIndex c=ci();
+        double xyz[dim];
+        for(int d=0;d<dim;++d)
+          xyz[d]=geom->getXLower()[d]
+            + dx[d]*(c[d]-cell_moduli_box.lower()[d] + 0.5);
+
+        int ijk(0), factor(1);
+        for(int d=0;d<dim;++d)
+          {
+            int i=static_cast<int>(xyz[d]*(lambda_ijk[d]-1)
+                                   /(lambda_xyz_max[d]-lambda_xyz_min[d]));
+            i=std::max(0,std::min(lambda_ijk[d]-1,i));
+            ijk+=i*factor;
+            factor*=lambda_ijk[d];
+          }
+        (*cell_moduli)(c,0)=lambda[ijk];
+      }
+
+    for(pdat::CellIterator ci(cell_moduli->getGhostBox()); ci; ci++)
+      {
+        pdat::CellIndex c=ci();
+        double xyz[dim];
+        for(int d=0;d<dim;++d)
+          xyz[d]=geom->getXLower()[d]
+            + dx[d]*(c[d]-cell_moduli_box.lower()[d] + 0.5);
+
+        int ijk(0), factor(1);
+        for(int d=0;d<dim;++d)
+          {
+            int i=static_cast<int>(xyz[d]*(mu_ijk[d]-1)
+                                   /(mu_xyz_max[d]-mu_xyz_min[d]));
+            i=std::max(0,std::min(mu_ijk[d]-1,i));
+            ijk+=i*factor;
+            factor*=mu_ijk[d];
+          }
+        (*cell_moduli)(c,1)=mu[ijk];
+      }
+
+    /* I do not think this is actually necessary. */
+    tbox::Pointer<pdat::CellData<double> > dp_data =
+      patch->getPatchData(dp_id);
+    dp_data->fill(0.0);
+
+    tbox::Pointer<pdat::CellData<double> > p_rhs_data =
+      patch->getPatchData(p_rhs_id);
+    p_rhs_data->fill(0.0);
+
+    /* v_rhs */
+    tbox::Pointer<pdat::SideData<double> > v_rhs_data =
+      patch->getPatchData(v_rhs_id);
+
+    if(v_rhs.empty())
+      {
+        v_rhs_data->fill(0,0);
+      }
+    else
+      {
+        double L(0.2),W(0.25);
+        double cdip(0.707107),sdip(0.707107);
+        //double cdip(0.),sdip(1.);
+        double cstrike(0.),sstrike(1.);
+        double cr(0.),sr(1.);
+        double delta(0.003);
+        double x(0.500001),y(0.5),z(0.5);
+        double beta(0.2);
+	double scale(-10.);
+
+        const double pi=4*atan(1);
+        const double theta(0);
+        // const double theta(pi/4);
+        const FTensor::Tensor1<double,3> center(x,y,z);
+        const FTensor::Tensor2<double,3,3> rot(std::cos(theta),std::sin(theta),0,
+                                               -std::sin(theta),cos(theta),0,
+                                               0,0,1);
+        FTensor::Tensor1<double,3> Dx[dim];
+        for(int d0=0;d0<dim;++d0)
+          {
+            for(int d1=0;d1<dim;++d1)
+              Dx[d0](d1)=0;
+            
+            Dx[d0](d0)=dx[d0];
+          }
+        FTensor::Tensor1<double,3> slip(0,scale,0);
+        FTensor::Index<'a',3> a;
+        FTensor::Index<'b',3> b;
+        FTensor::Tensor1<double,3> jump;
+        jump(a)=slip(b)*rot(b,a);
+
+        double fault[]={L,W};
+
+        hier::Box pbox = v_rhs_data->getBox();
+        for(int ix=0;ix<dim;++ix)
+          {
+            double offset[]={0.5,0.5,0.5};
+            offset[ix]=0;
+
+            for(pdat::SideIterator si(pbox,ix); si; si++)
+              {
+                pdat::SideIndex s=si();
+                (*v_rhs_data)(s)=0;
+
+                FTensor::Tensor1<double,3> xyz(0,0,0);
+                for(int d=0;d<dim;++d)
+                  xyz(d)=geom->getXLower()[d]
+                    + dx[d]*(s[d]-pbox.lower()[d]+offset[d]);
+
+                /* Rotate the coordinates into the coordinates of the
+                   fault.  So in those coordinates, if x<0, you are on
+                   the left, and if x>0, you are on the right. */
+                FTensor::Tensor1<double,3> ntt;
+                FTensor::Tensor1<double,3> ntt_dp[dim], ntt_dm[dim];
+                ntt(a)=rot(a,b)*(xyz(b)-center(b));
+                for(int d=0;d<dim;++d)
+                  {
+                    ntt_dp[d](a)=rot(a,b)*(xyz(b)+Dx[d](b)-center(b));
+                    ntt_dm[d](a)=rot(a,b)*(xyz(b)-Dx[d](b)-center(b));
+                  }
+
+                /* d/dx^2, d/dy^2, d/dz^2 */
+                for(int d=0;d<dim;++d)
+                  {
+                    int sign(0);
+                    if(ntt(0)<=0 && ntt_dp[d](0)>0
+                       && intersect_fault(dim,ntt,ntt_dp[d],fault))
+                      sign=1;
+                    else if(ntt(0)>0 && ntt_dp[d](0)<=0
+                            && intersect_fault(dim,ntt,ntt_dp[d],fault))
+                      sign=-1;
+                    else if(ntt(0)<=0 && ntt_dm[d](0)>0
+                            && intersect_fault(dim,ntt,ntt_dm[d],fault))
+                      sign=1;
+                    else if(ntt(0)>0 && ntt_dm[d](0)<=0
+                            && intersect_fault(dim,ntt,ntt_dm[d],fault))
+                      sign=-1;
+
+                    if(sign!=0)
+                      {
+                        const double lambda_here(1), mu_here(1);
+                        double factor(mu_here);
+                        if(ix==d)
+                          factor=lambda_here+2*mu_here;
+                        (*v_rhs_data)(s)+=sign*factor*jump(ix)/(dx[d]*dx[d]);
+                      }
+                  }
+
+                /* d/dxy */
+
+                for(int iy=(ix+1)%dim; iy!=ix; iy=(iy+1)%dim)
+                  {
+                    FTensor::Tensor1<double,3> ntt_dxy[2][2];
+                    ntt_dxy[0][0](a)=
+                      rot(a,b)*(xyz(b)+Dx[ix](b)/2+Dx[iy](b)/2-center(b));
+                    ntt_dxy[0][1](a)=
+                      rot(a,b)*(xyz(b)+Dx[ix](b)/2-Dx[iy](b)/2-center(b));
+                    ntt_dxy[1][0](a)=
+                      rot(a,b)*(xyz(b)-Dx[ix](b)/2+Dx[iy](b)/2-center(b));
+                    ntt_dxy[1][1](a)=
+                      rot(a,b)*(xyz(b)-Dx[ix](b)/2-Dx[iy](b)/2-center(b));
+
+                    const double lambda_here(1), mu_here(1);
+                    int l(0), m(0);
+                    double j(0);
+
+                    if(ntt_dxy[0][0](0)<=0 && ntt_dxy[1][0](0)>0
+                       && intersect_fault(dim,ntt_dxy[0][0],ntt_dxy[1][0],fault))
+                      m-=1;
+                    if(ntt_dxy[0][0](0)>0 && ntt_dxy[1][0](0)<=0
+                       && intersect_fault(dim,ntt_dxy[0][0],ntt_dxy[1][0],fault))
+                      m+=1;
+                    if(ntt_dxy[0][1](0)<=0 && ntt_dxy[1][1](0)>0
+                       && intersect_fault(dim,ntt_dxy[0][1],ntt_dxy[1][1],fault))
+                      m+=1;
+                    if(ntt_dxy[0][1](0)>0 && ntt_dxy[1][1](0)<=0
+                       && intersect_fault(dim,ntt_dxy[0][1],ntt_dxy[1][1],fault))
+                      m-=1;
+
+                    if(ntt_dxy[0][0](0)<=0 && ntt_dxy[0][1](0)>0
+                       && intersect_fault(dim,ntt_dxy[0][0],ntt_dxy[0][1],fault))
+                      l-=1;
+                    if(ntt_dxy[0][0](0)>0 && ntt_dxy[0][1](0)<=0
+                       && intersect_fault(dim,ntt_dxy[0][0],ntt_dxy[0][1],fault))
+                      l+=1;
+                    if(ntt_dxy[1][0](0)<=0 && ntt_dxy[1][1](0)>0
+                       && intersect_fault(dim,ntt_dxy[1][0],ntt_dxy[1][1],fault))
+                      l+=1;
+                    if(ntt_dxy[1][0](0)>0 && ntt_dxy[1][1](0)<=0
+                       && intersect_fault(dim,ntt_dxy[1][0],ntt_dxy[1][1],fault))
+                      l-=1;
+
+                    j=l*lambda_here + m*mu_here;
+
+                    if(j!=0)
+                      (*v_rhs_data)(s)+=j*jump(iy) / (dx[0]*dx[1]);
+                  }
+              }
+          }
+        // if(0)
+        //   {
+
+	// typedef struct {
+	// 	double x1s,x1i,x2s,x3s,x3i;
+	// } rpoint;
+
+	// rpoint xp00,xm00,x0p0,x0m0,x00p,x00m;
+	// double xr,yr,zr;
+        // double x2r;
+
+	// x2r= cstrike*x  -sstrike*y;
+	// xr = cdip   *x2r-sdip   *z;
+	// yr = sstrike*x  +cstrike*y;
+	// zr = sdip   *x2r+cdip   *z;
+
+        // hier::Box pbox = v_rhs_data->getBox();
+        // for(int ix=0;ix<dim;++ix)
+        //   {
+        //     double offset[]={0.5,0.5,0.5};
+        //     offset[ix]=0;
+
+        //     for(pdat::SideIterator si(pbox,ix); si; si++)
+        //       {
+        //         pdat::SideIndex s=si();
+        //         double xyz[dim];
+        //         for(int d=0;d<dim;++d)
+        //           xyz[d]=geom->getXLower()[d]
+        //             + dx[d]*(s[d]-pbox.lower()[d]+offset[d]);
+            
+	// 	double x1,x2,x3;
+	// 	double dx1,dx2,dx3;
+
+	// 	if (2==d_dim.getValue())
+	// 	{
+	// 		x1=0;
+	// 		x2=xyz[0];
+	// 		x3=xyz[1];
+	// 		dx1=dx[0];
+	// 		dx2=dx[0];
+	// 		dx3=dx[1];
+	// 	} else if (3==d_dim.getValue())
+	// 	{
+        //                 x1=xyz[0];
+	// 		x2=xyz[1];
+	// 		x3=xyz[2];
+	// 		dx1=dx[0];
+	// 		dx2=dx[1];
+	// 		dx3=dx[2];
+	// 	}
+
+	// 	double g0m0(1.),g0p0(1.),g00p(1.),g00m(1.),gm00(1.),gp00(1.);
+	// 	double x1s,x1i,x2s,x3s,x3i;
+
+        //         x2r= cstrike*x1-sstrike*x2;
+        //         x1s= cdip*x2r-sdip*x3;
+        //         x1i= cdip*x2r+sdip*x3;
+        //         x2s= sstrike*x1+cstrike*x2;
+        //         x3s= sdip*x2r+cdip*x3;
+        //         x3i=-sdip*x2r+cdip*x3;
+
+	// 	double n[]={cdip*cstrike,-cdip*sstrike,-sdip};
+	// 	double b[]={sstrike*cr+cstrike*sdip*sr,cstrike*cr-sstrike*sdip*sr,+cdip*sr};
+
+	// 	rotate(cstrike,sstrike,cdip,sdip,x1+dx1/2.,x2,x3,&(xp00.x1s),&(xp00.x1i),&(xp00.x2s),&(xp00.x3s),&(xp00.x3i));
+	// 	rotate(cstrike,sstrike,cdip,sdip,x1-dx1/2.,x2,x3,&(xm00.x1s),&(xm00.x1i),&(xm00.x2s),&(xm00.x3s),&(xm00.x3i));
+	// 	rotate(cstrike,sstrike,cdip,sdip,x1,x2+dx2/2.,x3,&(x0p0.x1s),&(x0p0.x1i),&(x0p0.x2s),&(x0p0.x3s),&(x0p0.x3i));
+	// 	rotate(cstrike,sstrike,cdip,sdip,x1,x2-dx2/2.,x3,&(x0m0.x1s),&(x0m0.x1i),&(x0m0.x2s),&(x0m0.x3s),&(x0m0.x3i));
+	// 	rotate(cstrike,sstrike,cdip,sdip,x1,x2,x3+dx3/2.,&(x00p.x1s),&(x00p.x1i),&(x00p.x2s),&(x00p.x3s),&(x00p.x3i));
+	// 	rotate(cstrike,sstrike,cdip,sdip,x1,x2,x3-dx3/2.,&(x00m.x1s),&(x00m.x1i),&(x00m.x2s),&(x00m.x3s),&(x00m.x3i));
+
+	// 	double temp1=gauss(x1s-xr,delta);
+	// 	double temp2(1.0);
+	// 	if (3==d_dim.getValue())
+	// 	{
+	// 		temp2=omega((x2s-yr)/L,beta);
+	// 	}
+	// 	double temp3=omega((x3s-zr)/W,beta);
+	// 	double sourc=(+(gp00*gauss(xp00.x1s-xr,delta)-gm00*gauss(xm00.x1s-xr,delta))*n[0]/dx1
+        //                       +(g0p0*gauss(x0p0.x1s-xr,delta)-g0m0*gauss(x0m0.x1s-xr,delta))*n[1]/dx2
+        //                       +(g00p*gauss(x00p.x1s-xr,delta)-g00m*gauss(x00m.x1s-xr,delta))*n[2]/dx3 )
+	// 		*temp2 
+	// 		*temp3;
+
+        //         double dblcp=temp1 
+        //                *( (gp00*omega((xp00.x2s-yr)/L,beta)-gm00*omega((xm00.x2s-yr)/L,beta))*b[0]/dx1
+        //                  +(g0p0*omega((x0p0.x2s-yr)/L,beta)-g0m0*omega((x0m0.x2s-yr)/L,beta))*b[1]/dx2
+        //                  +(g00p*omega((x00p.x2s-yr)/L,beta)-g00m*omega((x00m.x2s-yr)/L,beta))*b[2]/dx3 ) 
+        //                *temp3;
+
+	// 	double dipcs=temp1 
+	// 		*temp2 
+	// 		*(+(gp00*omega((xp00.x3s-zr)/W,beta)-gm00*omega((xm00.x3s-zr)/W,beta))*b[0]/dx1
+	// 		  +(g0p0*omega((x0p0.x3s-zr)/W,beta)-g0m0*omega((x0m0.x3s-zr)/W,beta))*b[1]/dx2
+	// 		  +(g00p*omega((x00p.x3s-zr)/W,beta)-g00m*omega((x00m.x3s-zr)/W,beta))*b[2]/dx3 );
+
+        //         temp1=gauss(x1i-xr,delta);
+        //         temp3=omega((x3i+zr)/W,beta);
+        //         // double image=( (gp00*gauss(xp00.x1i-xr,delta)-gm00*gauss(xm00.x1i-xr,delta))*n[0]/dx1
+        //         //               +(g0p0*gauss(x0p0.x1i-xr,delta)-g0m0*gauss(x0m0.x1i-xr,delta))*n[1]/dx2
+        //         //               +(g00p*gauss(x00p.x1i-xr,delta)-g00m*gauss(x00m.x1i-xr,delta))*n[2]/dx3 )
+        //         //      *temp2 
+        //         //      *temp3;
+        //         // double cplei=temp1 
+        //         //             *( (gp00*omega((xp00.x2s-yr)/L,beta)-gm00*omega((xp00.x2s-yr)/L,beta))*b[0]/dx1
+        //         //               +(g0p0*omega((x0p0.x2s-yr)/L,beta)-g0m0*omega((x0p0.x2s-yr)/L,beta))*b[1]/dx2
+        //         //               +(g00p*omega((x00p.x2s-yr)/L,beta)-g00m*omega((x00p.x2s-yr)/L,beta))*b[2]/dx3 ) 
+        //         //             *temp3;
+        //         // double dipci=temp1 
+        //         //             *temp2 
+        //         //             *( (gp00*omega((xp00.x3i+zr)/W,beta)-gm00*omega((xm00.x3i+zr)/W,beta))*b[0]/dx1
+        //         //               +(g0p0*omega((x0p0.x3i+zr)/W,beta)-g0m0*omega((x0m0.x3i+zr)/W,beta))*b[1]/dx2
+        //         //               +(g00p*omega((x00p.x3i+zr)/W,beta)-g00m*omega((x00m.x3i+zr)/W,beta))*b[2]/dx3 );
+ 
+       	// 	// force update
+	// 	switch (d_dim.getValue()-ix-1)
+	// 	{
+	// 		case 2:{
+	// 			// f_1
+	// 			double f1=+cr*sstrike*sourc
+	// 				  +cr*cdip*cstrike*dblcp
+	// 				  +sr*cdip*cstrike*dipcs
+	// 				  +sr*sdip*cstrike*sourc;
+        //         		(*v_rhs_data)(s)=-f1*scale;
+	// 			break;
+	// 		       }
+	// 		case 1:{
+	// 		       // f_2
+	// 			double f2=+cr*cstrike*sourc
+	// 				  -cr*cdip*sstrike*dblcp
+	// 				  -sr*cdip*sstrike*dipcs
+	// 				  -sr*sdip*sstrike*sourc;
+        //         		(*v_rhs_data)(s)=-f2*scale;
+	// 			break;
+	// 		       }
+	// 		case 0:{
+	// 			// f_3
+	// 			double f3=-cr*sdip*dblcp
+	// 				  +sr*cdip*sourc
+	// 				  -sr*sdip*dipcs;
+	// 			(*v_rhs_data)(s)=-f3*scale;
+	// 		       }
+	// 	}
+
+        //       }
+        //     int i=1;
+        //     for(int d=0;d<dim;++d)
+        //       i*=v_rhs_ijk[d];
+        //   }
+        //   }
+      }
+  }    // End patch loop.
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FAC/packDerivedDataIntoDoubleBuffer.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FAC/packDerivedDataIntoDoubleBuffer.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,117 @@
+/*************************************************************************
+ *
+ * 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:   Numerical routines for example FAC Elastic solver 
+ *
+ ************************************************************************/
+#include "Elastic/FAC.h"
+
+#include "SAMRAI/hier/IntVector.h"
+#include "SAMRAI/geom/CartesianGridGeometry.h"
+#include "SAMRAI/geom/CartesianPatchGeometry.h"
+#include "SAMRAI/solv/SimpleCellRobinBcCoefs.h"
+#include "SAMRAI/pdat/CellData.h"
+#include "SAMRAI/math/HierarchyCellDataOpsReal.h"
+#include "SAMRAI/pdat/SideData.h"
+#include "SAMRAI/tbox/Utilities.h"
+#include "SAMRAI/hier/Variable.h"
+#include "SAMRAI/hier/VariableDatabase.h"
+
+namespace SAMRAI {
+
+  /*
+*************************************************************************
+* Write derived data to the given stream.                               *
+*************************************************************************
+*/
+  bool Elastic::FAC::packDerivedDataIntoDoubleBuffer(
+                                                     double* buffer,
+                                                     const hier::Patch& patch,
+                                                     const hier::Box& region,
+                                                     const std::string&
+                                                     variable_name,
+                                                     int depth_id) const
+  {
+    pdat::CellData<double>::Iterator icell(region);
+
+	tbox::Pointer<pdat::SideData<double> > v_ptr;
+	if (variable_name == "Displacement") {
+		v_ptr = patch.getPatchData(v_id);
+	}
+	else if ("Equivalent body force" == variable_name)
+	{
+		v_ptr = patch.getPatchData(v_rhs_id);
+	}
+	else
+	{
+		// Did not register this name.
+		TBOX_ERROR(
+		"Unregistered variable name '" << variable_name << "' in\n"
+		<<
+		"Elastic::FAC::packDerivedDataIntoDoubleBuffer");
+	}
+
+	pdat::SideData<double>& v = *v_ptr;
+        if(d_dim.getValue()==2)
+          {
+            const hier::Index ip(1,0), jp(0,1);
+            for ( ; icell; icell++) {
+
+              pdat::CellIndex center(*icell);
+              const pdat::SideIndex
+		x(center,0,pdat::SideIndex::Lower),
+		y(center,1,pdat::SideIndex::Lower);
+	
+              double vx=(v(x+ip) + v(x))/2.;
+              double vy=(v(y+jp) + v(y))/2.;
+
+              if (0==depth_id)
+		{
+                  *buffer = vx;
+		}
+              else
+		{
+                  *buffer = vy;
+		}
+              buffer = buffer + 1;
+            }
+          }
+        else
+          {
+            const hier::Index ip(1,0,0), jp(0,1,0), kp(0,0,1);
+            for ( ; icell; icell++) {
+
+              pdat::CellIndex center(*icell);
+              const pdat::SideIndex
+		x(center,0,pdat::SideIndex::Lower),
+		y(center,1,pdat::SideIndex::Lower),
+		z(center,2,pdat::SideIndex::Lower);
+	
+              double vx=(v(x+ip) + v(x))/2.;
+              double vy=(v(y+jp) + v(y))/2.;
+              double vz=(v(z+kp) + v(z))/2.;
+
+              if (0==depth_id)
+		{
+                  *buffer = vx;
+		}
+              else if (1==depth_id)
+		{
+                  *buffer = vy;
+		}
+              else
+                {
+                  *buffer = vz;
+                }
+              buffer = buffer + 1;
+            }
+          }
+    // Return true if this patch has derived data on it.
+    // False otherwise.
+    return true;
+  }
+
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FAC/resetHierarchyConfiguration.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FAC/resetHierarchyConfiguration.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,41 @@
+/*************************************************************************
+ *
+ * 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:   Numerical routines for example FAC Elastic solver 
+ *
+ ************************************************************************/
+#include "Elastic/FAC.h"
+
+#include "SAMRAI/hier/IntVector.h"
+#include "SAMRAI/geom/CartesianGridGeometry.h"
+#include "SAMRAI/geom/CartesianPatchGeometry.h"
+#include "SAMRAI/solv/SimpleCellRobinBcCoefs.h"
+#include "SAMRAI/pdat/CellData.h"
+#include "SAMRAI/math/HierarchyCellDataOpsReal.h"
+#include "SAMRAI/pdat/SideData.h"
+#include "SAMRAI/tbox/Utilities.h"
+#include "SAMRAI/hier/Variable.h"
+#include "SAMRAI/hier/VariableDatabase.h"
+
+namespace SAMRAI {
+
+  /*
+*************************************************************************
+* Reset the hierarchy-dependent internal information.                   *
+*************************************************************************
+*/
+  void Elastic::FAC::resetHierarchyConfiguration
+  (tbox::Pointer<hier::BasePatchHierarchy> new_hierarchy,
+   int coarsest_level,
+   int finest_level)
+  {
+    (void)coarsest_level;
+    (void)finest_level;
+
+    d_hierarchy = new_hierarchy;
+  }
+
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FAC/setupPlotter.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FAC/setupPlotter.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,66 @@
+/*************************************************************************
+ *
+ * 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:   Numerical routines for example FAC Elastic solver 
+ *
+ ************************************************************************/
+#include "Elastic/FAC.h"
+
+#include "SAMRAI/hier/IntVector.h"
+#include "SAMRAI/geom/CartesianGridGeometry.h"
+#include "SAMRAI/geom/CartesianPatchGeometry.h"
+#include "SAMRAI/solv/SimpleCellRobinBcCoefs.h"
+#include "SAMRAI/pdat/CellData.h"
+#include "SAMRAI/math/HierarchyCellDataOpsReal.h"
+#include "SAMRAI/pdat/SideData.h"
+#include "SAMRAI/tbox/Utilities.h"
+#include "SAMRAI/hier/Variable.h"
+#include "SAMRAI/hier/VariableDatabase.h"
+
+namespace SAMRAI {
+
+#ifdef HAVE_HDF5
+  /*
+*************************************************************************
+* Set up external plotter to plot internal data from this class.        *
+* Register variables appropriate for plotting.                          *
+*************************************************************************
+*/
+  int Elastic::FAC::setupPlotter(appu::VisItDataWriter& plotter) const {
+    if (d_hierarchy.isNull()) {
+      TBOX_ERROR(d_object_name << ": No hierarchy in\n"
+                 << " Elastic::FAC::setupPlotter\n"
+                 << "The hierarchy must be set before calling\n"
+                 << "this function.\n");
+    }
+    plotter.registerPlotQuantity("Pressure",
+                                 "SCALAR",
+                                 p_id);
+    plotter.registerDerivedPlotQuantity("Displacement",
+                                        "VECTOR",
+                                        (appu::VisDerivedDataStrategy *)this);
+    plotter.registerDerivedPlotQuantity("Equivalent body force",
+                                        "VECTOR",
+                                        (appu::VisDerivedDataStrategy *)this);
+    plotter.registerPlotQuantity("Exact solution",
+                                 "SCALAR",
+                                 p_exact_id);
+    plotter.registerPlotQuantity("Cell lambda",
+                                 "SCALAR",
+                                 cell_moduli_id,0);
+		// this, below, doesn't seem to work.
+    plotter.registerPlotQuantity("Cell mu",
+                                 "SCALAR",
+                                 cell_moduli_id,1);
+    plotter.registerPlotQuantity("Elastic source",
+                                 "SCALAR",
+                                 p_rhs_id);
+
+    return 0;
+  }
+#endif
+
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FAC/solve.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FAC/solve.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,159 @@
+/*************************************************************************
+ *
+ * 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:   Numerical routines for example FAC Elastic solver 
+ *
+ ************************************************************************/
+#include "Elastic/FAC.h"
+
+#include "SAMRAI/hier/IntVector.h"
+#include "SAMRAI/geom/CartesianGridGeometry.h"
+#include "SAMRAI/geom/CartesianPatchGeometry.h"
+#include "SAMRAI/solv/SimpleCellRobinBcCoefs.h"
+#include "SAMRAI/pdat/CellData.h"
+#include "SAMRAI/math/HierarchyCellDataOpsReal.h"
+#include "SAMRAI/pdat/SideData.h"
+#include "SAMRAI/tbox/Utilities.h"
+#include "SAMRAI/hier/Variable.h"
+#include "SAMRAI/hier/VariableDatabase.h"
+
+/*
+*************************************************************************
+* Set up the initial guess and problem parameters                       *
+* and solve the Elastic problem.  We explicitly initialize and          *
+* deallocate the solver state in this example.                          *
+*************************************************************************
+*/
+int SAMRAI::Elastic::FAC::solve()
+{
+
+  if (d_hierarchy.isNull()) {
+    TBOX_ERROR(d_object_name
+               << "Cannot solve using an uninitialized object.\n");
+  }
+
+  int ln;
+  /*
+   * Fill in the initial guess.
+   */
+  for (ln = 0; ln <= d_hierarchy->getFinestLevelNumber(); ++ln) {
+    tbox::Pointer<hier::PatchLevel> level = d_hierarchy->getPatchLevel(ln);
+    hier::PatchLevel::Iterator ip(*level);
+    for ( ; ip; ip++) {
+      tbox::Pointer<hier::Patch> patch = *ip;
+      tbox::Pointer<pdat::CellData<double> >
+        p = patch->getPatchData(p_id);
+
+      tbox::Pointer<geom::CartesianPatchGeometry>
+        geom = patch->getPatchGeometry();
+
+      if(p_initial.empty())
+        {
+          p->fill(0.0);
+        }
+      else
+        {
+          const int dim=d_dim.getValue();
+          const double *dx=geom->getDx();
+          double dx_p[dim];
+          for(int d=0;d<dim;++d)
+            dx_p[d]=(p_initial_xyz_max[d]
+                     - p_initial_xyz_min[d])/(p_initial_ijk[d]-1);
+          int di[dim];
+          di[0]=1;
+          for(int d=1;d<dim;++d)
+            di[d]=di[d-1]*p_initial_ijk[d-1];
+
+          hier::Box pbox = p->getBox();
+          for(pdat::CellIterator ci(p->getGhostBox()); ci; ci++)
+            {
+              pdat::CellIndex c=ci();
+              double xyz[dim], weight[dim][2];
+              for(int d=0;d<dim;++d)
+                xyz[d]=geom->getXLower()[d]
+                  + dx[d]*(c[d]-pbox.lower()[d] + 0.5);
+
+              int ijk(0);
+              int ddi[dim];
+              for(int d=0;d<dim;++d)
+                {
+                  int i=static_cast<int>(xyz[d]*(p_initial_ijk[d]-1)
+                                         /(p_initial_xyz_max[d]
+                                           - p_initial_xyz_min[d]));
+                  i=std::max(0,std::min(p_initial_ijk[d]-1,i));
+                  ijk+=i*di[d];
+
+                  if(i==p_initial_ijk[d]-1)
+                    {
+                      weight[d][0]=1;
+                      weight[d][1]=0;
+                      ddi[d]=0;
+                    }
+                  else
+                    {
+                      weight[d][1]=
+                        (xyz[d]-(i*dx_p[d] + p_initial_xyz_min[d]))/dx_p[d];
+                      weight[d][0]=1-weight[d][1];
+                      ddi[d]=di[d];
+                    }
+                }
+
+              if(dim==2)
+                {
+                  (*p)(c)=p_initial[ijk]*weight[0][0]*weight[1][0]
+                    + p_initial[ijk+ddi[0]]*weight[0][1]*weight[1][0]
+                    + p_initial[ijk+ddi[1]]*weight[0][0]*weight[1][1]
+                    + p_initial[ijk+ddi[0]+ddi[1]]*weight[0][1]*weight[1][1];
+                }
+              else
+                {
+                  (*p)(c)=p_initial[ijk]*weight[0][0]*weight[1][0]*weight[2][0]
+                    + p_initial[ijk+ddi[0]]*weight[0][1]*weight[1][0]*weight[2][0]
+                    + p_initial[ijk+ddi[1]]*weight[0][0]*weight[1][1]*weight[2][0]
+                    + p_initial[ijk+ddi[0]+ddi[1]]*weight[0][1]*weight[1][1]*weight[2][0]
+                    
+                    + p_initial[ijk+ddi[2]]*weight[0][0]*weight[1][0]*weight[2][1]
+                    + p_initial[ijk+ddi[0]+ddi[2]]*weight[0][1]*weight[1][0]*weight[2][1]
+                    + p_initial[ijk+ddi[1]+ddi[2]]*weight[0][0]*weight[1][1]*weight[2][1]
+                    + p_initial[ijk+ddi[0]+ddi[1]+ddi[2]]*weight[0][1]*weight[1][1]*weight[2][1];
+                }
+            }
+        }
+
+      tbox::Pointer<pdat::SideData<double> >
+        v = patch->getPatchData(v_id);
+      v->fill(0.0);
+    }
+    d_elastic_fac_solver.set_boundaries(p_id,v_id,level,false);
+  }
+
+  fix_moduli();
+
+  d_elastic_fac_solver.initializeSolverState
+    (p_id,cell_moduli_id,edge_moduli_id,dp_id,p_rhs_id,v_id,v_rhs_id,
+     d_hierarchy,0,d_hierarchy->getFinestLevelNumber());
+
+  tbox::plog << "solving..." << std::endl;
+  int solver_ret;
+  solver_ret = d_elastic_fac_solver.solveSystem(p_id,p_rhs_id,v_id,v_rhs_id);
+  /*
+   * Present data on the solve.
+   */
+  // double avg_factor, final_factor;
+  // d_elastic_fac_solver.getConvergenceFactors(avg_factor, final_factor);
+  // tbox::plog << "\t" << (solver_ret ? "" : "NOT ") << "converged " << "\n"
+  //            << "	iterations: "
+  //            << d_elastic_fac_solver.getNumberOfIterations() << "\n"
+  //            << "	residual: "<< d_elastic_fac_solver.getResidualNorm()
+  //            << "\n"
+  //            << "	average convergence: "<< avg_factor << "\n"
+  //            << "	final convergence: "<< final_factor << "\n"
+  //            << std::flush;
+
+  d_elastic_fac_solver.deallocateSolverState();
+
+  return 0;
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps.I
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps.I	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,201 @@
+/*************************************************************************
+ *
+ * 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 Elastic using FAC 
+ *
+ ************************************************************************/
+namespace SAMRAI {
+namespace solv {
+
+SAMRAI_INLINE_KEYWORD
+void Elastic::FACOps::setPreconditioner(
+   const FACPreconditioner* preconditioner) {
+   d_preconditioner = preconditioner;
+}
+
+#ifdef HAVE_HYPRE
+SAMRAI_INLINE_KEYWORD
+void Elastic::FACOps::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 Elastic::FACOps::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
+// }
+
+/*
+ ********************************************************************
+ ********************************************************************
+ */
+
+SAMRAI_INLINE_KEYWORD
+void Elastic::FACOps::enableLogging(
+   bool enable_logging)
+{
+   d_enable_logging = enable_logging;
+}
+
+/*
+ ********************************************************************
+ * Set the choice for smoothing algorithm.                          *
+ ********************************************************************
+ */
+
+SAMRAI_INLINE_KEYWORD
+void Elastic::FACOps::setSmoothingChoice(
+   const std::string& smoothing_choice)
+{
+#ifdef DEBUG_CHECK_ASSERTIONS
+   if (smoothing_choice != "Tackley" && smoothing_choice != "Gerya") {
+      TBOX_ERROR(d_object_name << ": Bad smoothing choice '"
+                               << smoothing_choice
+                               << "' in Elastic::FACOps::setSmoothingChoice.");
+   }
+#endif
+   d_smoothing_choice = smoothing_choice;
+}
+
+/*
+ ********************************************************************
+ * Set the choice for the coarse level solver.                      *
+ ********************************************************************
+ */
+
+SAMRAI_INLINE_KEYWORD
+void Elastic::FACOps::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 == "Tackley"
+       || choice == "Gerya"
+       || choice == "hypre") {
+      d_coarse_solver_choice = choice;
+   } else {
+      TBOX_ERROR(
+         d_object_name << ": Bad coarse level solver choice '"
+         << choice
+         <<
+         "' in Elastic::FACOps::setCoarseLevelSolver.");
+   }
+}
+
+/*
+ ********************************************************************
+ * Set the tolerance for the coarse level solver.                   *
+ ********************************************************************
+ */
+
+SAMRAI_INLINE_KEYWORD
+void Elastic::FACOps::setCoarsestLevelSolverTolerance(
+   double tol) {
+   d_coarse_solver_tolerance = tol;
+}
+
+/*
+ ********************************************************************
+ * Set the tolerance for the coarse level solver.                   *
+ ********************************************************************
+ */
+
+SAMRAI_INLINE_KEYWORD
+void Elastic::FACOps::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 Elastic::FACOps::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 Elastic::FACOps::set_P_ProlongationMethod(
+   const std::string& prolongation_method) {
+#ifdef DEBUG_CHECK_ASSERTIONS
+   if (d_hierarchy) {
+      TBOX_ERROR(
+         d_object_name << ": Cannot change p prolongation method\n"
+         <<
+         "while operator state is initialized because that\n"
+         << "causes a corruption in the state.\n");
+   }
+#endif
+   p_prolongation_method = prolongation_method;
+}
+
+SAMRAI_INLINE_KEYWORD
+void Elastic::FACOps::set_V_ProlongationMethod(
+   const std::string& prolongation_method) {
+#ifdef DEBUG_CHECK_ASSERTIONS
+   if (d_hierarchy) {
+      TBOX_ERROR(
+         d_object_name << ": Cannot change v prolongation method\n"
+         <<
+         "while operator state is initialized because that\n"
+         << "causes a corruption in the state.\n");
+   }
+#endif
+   v_prolongation_method = prolongation_method;
+}
+
+}
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps.h	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,1079 @@
+/*************************************************************************
+ *
+ * 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 Elastic using FAC 
+ *
+ ************************************************************************/
+#ifndef GAMRA_ELASTIC_FACOPS_H
+#define GAMRA_ELASTIC_FACOPS_H
+
+#include "SAMRAI/SAMRAI_config.h"
+
+#include "SAMRAI/solv/FACPreconditioner.h"
+#include "SAMRAI/solv/FACOperatorStrategy.h"
+#include "Elastic/HypreSolver.h"
+#include "SAMRAI/solv/SAMRAIVectorReal.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 "Elastic/P_Refine_Patch_Strategy.h"
+#include "Elastic/V_Refine_Patch_Strategy.h"
+#include "Elastic/V_Coarsen_Patch_Strategy.h"
+
+#include <string>
+
+namespace SAMRAI {
+  namespace solv {
+    namespace Elastic {
+
+      /*!
+       * @brief FAC operator class to solve Elastic'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 Elastic's equation using a cell-centered
+       * second-order finite-volume discretization.
+       * It is designed to provide all operations specific to
+       * the scalar Elastic's equation,
+       * @f[ \nabla \cdot D \nabla u + C u = f @f]
+       * (see Elastic::Specifications) 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 Elastic-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 Elastic::Specifications 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 = "Tackley"     // see setSmoothingChoice()
+       * cf_discretization = "Ewing"       // see setCoarseFineDiscretization()
+       * prolongation_method = "P_REFINE" // see setProlongationMethod()
+       * hypre_solver = { ... }            // tbox::Database for initializing Hypre solver
+       * @endverbatim
+       */
+      class FACOps:
+        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
+         */
+        FACOps(
+               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.
+         */
+        ~FACOps(void) {}
+
+        /*!
+         * @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:
+         * - "Tackley"
+         * - "Gerya"
+         */
+        void
+        setSmoothingChoice(
+                           const std::string& smoothing_choice);
+
+        /*!
+         * @brief Set coarse level solver.
+         *
+         * Select from these:
+         * - @c "Tackley" (red-black smoothing until convergence--very slow!)
+         * - @c "Gerya" (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
+        set_P_ProlongationMethod(
+                                 const std::string& prolongation_method);
+
+        void
+        set_V_ProlongationMethod(
+                                 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 set_moduli_id(const int &cell_moduli, const int &edge_moduli)
+        {
+          cell_moduli_id=cell_moduli;
+          edge_moduli_id=edge_moduli;
+        }
+        //@}
+
+        /*!
+         * @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);
+
+        /*!
+         * @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);
+
+        //@{ @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);
+
+        void residual_2D
+        (pdat::CellData<double> &p,
+         pdat::SideData<double> &v,
+         pdat::CellData<double> &cell_moduli,
+         pdat::CellData<double> &p_rhs,
+         pdat::SideData<double> &v_rhs,
+         pdat::CellData<double> &p_resid,
+         pdat::SideData<double> &v_resid,
+         hier::Patch &patch,
+         const hier::Box &pbox,
+         const geom::CartesianPatchGeometry &geom);
+
+        void residual_3D
+        (pdat::CellData<double> &p,
+         pdat::SideData<double> &v,
+         pdat::CellData<double> &cell_moduli,
+         pdat::CellData<double> &p_rhs,
+         pdat::SideData<double> &v_rhs,
+         pdat::CellData<double> &p_resid,
+         pdat::SideData<double> &v_resid,
+         hier::Patch &patch,
+         const hier::Box &pbox,
+         const geom::CartesianPatchGeometry &geom);
+
+        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);
+
+        void set_boundaries(const int &p_id, const int &v_id, const int &l)
+        {
+          set_boundaries(p_id,v_id,l,true);
+        }
+        void set_boundaries(const int &p_id, const int &v_id, const int &l,
+                            const bool &rhs)
+        {
+          tbox::Pointer<hier::PatchLevel> level = d_hierarchy->getPatchLevel(l);
+          set_boundaries(p_id,v_id,level,rhs);
+        }
+        void set_boundaries(const int &p_id, const int &v_id,
+                            tbox::Pointer<hier::PatchLevel> &level)
+        {
+          set_boundaries(p_id,v_id,level,true);
+        }
+        void set_boundaries(const int &p_id, const int &v_id, 
+                            tbox::Pointer<hier::PatchLevel> &level,
+                            const bool &rhs);
+
+        //@}
+
+      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 smooth_Tackley_2D(
+                               SAMRAIVectorReal<double>& error,
+                               const SAMRAIVectorReal<double>& residual,
+                               int ln,
+                               int num_sweeps,
+                               double residual_tolerance = -1.0);
+
+        void smooth_Tackley_3D
+        (SAMRAIVectorReal<double>& solution,
+         const SAMRAIVectorReal<double>& residual,
+         int ln,
+         int num_sweeps,
+         double residual_tolerance = -1.0);
+
+        void smooth_V_2D(const int &axis,
+                         const hier::Box &pbox,
+                         tbox::Pointer<geom::CartesianPatchGeometry> &geom,
+                         const pdat::CellIndex &center,
+                         const hier::Index &ip,
+                         const hier::Index &jp,
+                         pdat::SideData<double> &v,
+                         pdat::SideData<double> &v_rhs,
+                         double &maxres,
+                         const double &dx,
+                         const double &dy,
+                         pdat::CellData<double> &cell_moduli,
+                         pdat::NodeData<double> &edge_moduli,
+                         const double &theta_momentum);
+
+        void smooth_V_3D(const int &ix,
+                         const hier::Box &pbox,
+                         tbox::Pointer<geom::CartesianPatchGeometry> &geom,
+                         pdat::SideData<double> &v,
+                         pdat::SideData<double> &v_rhs,
+                         pdat::CellData<double> &cell_moduli,
+                         pdat::EdgeData<double> &edge_moduli,
+                         const pdat::CellIndex &center,
+                         const double Dx[3],
+                         const double &theta_momentum,
+                         const hier::Index pp[3],
+                         double &maxres);
+
+        /* The mixed derivative of the stress.  We have to use a template
+           because 2D uses Node's for the edge moduli, while 3D uses
+           Edge's.  Written as if it is dtau_xy_dy. */
+
+        template<class E_data, class E_index>
+        double shear_noncell(const pdat::SideData<double> &v,
+                             const E_data &edge_moduli,
+                             const pdat::SideIndex &x,
+                             const pdat::SideIndex &y,
+                             const E_index &edge,
+                             const hier::Index &ip,
+                             const hier::Index &jp,
+                             const double &dx,
+                             const double &dy)
+        {
+          return 
+            edge_moduli(edge+jp,1)*(v(x+jp)-v(x   ))/(dy*dy)
+            -edge_moduli(edge   ,1)*(v(x   )-v(x-jp))/(dy*dy)
+            +edge_moduli(edge+jp,1)*(v(y+jp)-v(y+jp-ip))/(dx*dy) 
+            -edge_moduli(edge   ,1)*(v(y   )-v(y-ip   ))/(dx*dy);
+        }
+
+        /* The action of the velocity operator. It is written from the
+           perspective of vx, but pass in different values for center_x
+           etc. to get vy. */
+
+        double aligned_terms(const pdat::SideData<double> &v,
+                             const pdat::CellData<double> &cell_moduli,
+                             const pdat::CellIndex &center,
+                             const pdat::SideIndex &x,
+                             const hier::Index &ip,
+                             const double &dx)
+        {
+          return ( (v(x+ip)-v(x   ))*(cell_moduli(center   ,0)+2*cell_moduli(center   ,1))
+                   -(v(x   )-v(x-ip))*(cell_moduli(center-ip,0)+2*cell_moduli(center-ip,1)))/(dx*dx);
+        }
+
+        double lame_mixed(const pdat::SideData<double> &v,
+                          const pdat::CellData<double> &cell_moduli,
+                          const pdat::CellIndex &center,
+                          const pdat::SideIndex &y,
+                          const hier::Index &ip,
+                          const hier::Index &jp,
+                          const double &dx,
+                          const double &dy)
+        {
+          return (+ cell_moduli(center   ,0)*(v(y+jp   )-v(y   ))/dy
+                  - cell_moduli(center-ip,0)*(v(y+jp-ip)-v(y-ip))/dy)/dx;
+        }
+
+        double v_operator_2D(const pdat::SideData<double> &v,
+                             const pdat::CellData<double> &cell_moduli,
+                             const pdat::NodeData<double> &edge_moduli,
+                             const pdat::CellIndex &center,
+                             const pdat::NodeIndex &edge,
+                             const pdat::SideIndex &x,
+                             const pdat::SideIndex &y,
+                             const hier::Index &ip,
+                             const hier::Index &jp,
+                             const double &dx,
+                             const double &dy)
+        {
+          return aligned_terms(v,cell_moduli,center,x,ip,dx)
+            +lame_mixed(v,cell_moduli,center,y,ip,jp,dx,dy)
+            +shear_noncell(v,edge_moduli,x,y,edge,ip,jp,dx,dy);
+        }
+
+        double v_operator_3D(const pdat::SideData<double> &v,
+                             const pdat::CellData<double> &cell_moduli,
+                             const pdat::EdgeData<double> &edge_moduli,
+                             const pdat::CellIndex &center,
+                             const pdat::EdgeIndex &edge_y,
+                             const pdat::EdgeIndex &edge_z,
+                             const pdat::SideIndex &x,
+                             const pdat::SideIndex &y,
+                             const pdat::SideIndex &z,
+                             const hier::Index &ip,
+                             const hier::Index &jp,
+                             const hier::Index &kp,
+                             const double &dx,
+                             const double &dy,
+                             const double &dz)
+        {
+          return aligned_terms(v,cell_moduli,center,x,ip,dx)
+            +lame_mixed(v,cell_moduli,center,y,ip,jp,dx,dy)
+            +lame_mixed(v,cell_moduli,center,z,ip,kp,dx,dz)
+            +shear_noncell(v,edge_moduli,x,y,edge_y,ip,jp,dx,dy)
+            +shear_noncell(v,edge_moduli,x,z,edge_z,ip,kp,dx,dz);
+        }
+
+        /*!
+         * @brief Solve the coarsest level using HYPRE
+         */
+        int
+        solveCoarsestLevel_HYPRE(
+                                 SAMRAIVectorReal<double>& error,
+                                 const SAMRAIVectorReal<double>& residual,
+                                 int ln);
+
+        /*!
+         * @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():
+         *        prolongation_refine_operator
+         *        prolongation_refine_schedules
+         *   <li> xeqScheduleURestriction():
+         *        d_restriction_coarsen_operator,
+         *        urestriction_coarsen_schedules.
+         *   <li> xeqScheduleRRestriction():
+         *        restriction_coarsen_operator,
+         *        rrestriction_coarsen_schedules.
+         *   <li> xeqScheduleFluxCoarsen():
+         *        d_flux_coarsen_operator,
+         *        d_flux_coarsen_schedules.
+         *   <li> xeqScheduleGhostFill():
+         *        ghostfill_refine_operator,
+         *        ghostfill_refine_schedules.
+         *   <li> xeqScheduleGhostFillNoCoarse():
+         *        ghostfill_nocoarse_refine_operator,
+         *        ghostfill_nocoarse_refine_schedules.
+         * </ol>
+         *
+         * @return refinement schedule for prolongation
+         */
+        void
+        xeqScheduleProlongation(int p_dst, int p_src, int p_scr,
+                                int v_dst, int v_src, int v_scr,
+                                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 p_dst, int p_src, int v_dst, int v_src,
+                                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 p_dst, int p_src, int v_dst, int v_src,
+                                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 p_id, int v_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 p_id, int v_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 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 p_prolongation_method;
+        std::string v_prolongation_method;
+        std::string p_rrestriction_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 moduli and dp.
+         *
+         * @see set_moduli_dp_id.
+         */
+        int cell_moduli_id, edge_moduli_id, dp_id;
+
+#ifdef HAVE_HYPRE
+        /*!
+         * @brief HYPRE coarse-level solver object.
+         */
+        Elastic::HypreSolver 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_side_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, d_side_scratch_id;
+
+        //@}
+
+        //@{
+        /*!
+         * @name Various refine and coarsen objects used internally.
+         */
+
+        //! @brief Error prolongation (refinement) operator.
+        tbox::Pointer<xfer::RefineOperator> p_prolongation_refine_operator;
+        tbox::Array<tbox::Pointer<xfer::RefineSchedule> >
+        p_prolongation_refine_schedules;
+
+        tbox::Pointer<xfer::RefineOperator> v_prolongation_refine_operator;
+        tbox::Array<tbox::Pointer<xfer::RefineSchedule> >
+        v_prolongation_refine_schedules;
+
+        //! @brief Solution restriction (coarsening) operator.
+        tbox::Pointer<xfer::CoarsenOperator> p_urestriction_coarsen_operator;
+        tbox::Array<tbox::Pointer<xfer::CoarsenSchedule> >
+        p_urestriction_coarsen_schedules;
+
+        tbox::Pointer<xfer::CoarsenOperator> v_urestriction_coarsen_operator;
+        tbox::Array<tbox::Pointer<xfer::CoarsenSchedule> >
+        v_urestriction_coarsen_schedules;
+
+        //! @brief Residual restriction (coarsening) operator.
+        tbox::Pointer<xfer::CoarsenOperator> p_rrestriction_coarsen_operator;
+        tbox::Array<tbox::Pointer<xfer::CoarsenSchedule> >
+        p_rrestriction_coarsen_schedules;
+
+        tbox::Pointer<xfer::CoarsenOperator> v_rrestriction_coarsen_operator;
+        tbox::Array<tbox::Pointer<xfer::CoarsenSchedule> >
+        v_rrestriction_coarsen_schedules;
+
+        //! @brief Refine operator for data from coarser level.
+        tbox::Pointer<xfer::RefineOperator> p_ghostfill_refine_operator;
+        tbox::Array<tbox::Pointer<xfer::RefineSchedule> >
+        p_ghostfill_refine_schedules;
+
+        tbox::Pointer<xfer::RefineOperator> v_ghostfill_refine_operator;
+        tbox::Array<tbox::Pointer<xfer::RefineSchedule> >
+        v_ghostfill_refine_schedules;
+
+        //! @brief Refine operator for data from same level.
+        tbox::Array<tbox::Pointer<xfer::RefineSchedule> >
+        p_nocoarse_refine_schedules;
+
+        tbox::Array<tbox::Pointer<xfer::RefineSchedule> >
+        v_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 the patch strategies the patch data index we want
+         * to set and whether we are setting data with homogeneous
+         * boundary condition.
+         */
+        P_Refine_Patch_Strategy p_refine_patch_strategy;
+        V_Refine_Patch_Strategy v_refine_patch_strategy;
+        V_Coarsen_Patch_Strategy v_coarsen_patch_strategy;
+
+        //@{
+        /*!
+         * @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 "Elastic/FACOps.I"
+#endif
+
+#endif // included_solv_ElasticFACOps
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps/FACOps.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps/FACOps.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,193 @@
+/*************************************************************************
+ *
+ * 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 Elastic using FAC 
+ *
+ ************************************************************************/
+#include "Elastic/FACOps.h"
+
+#ifndef SAMRAI_INLINE
+#include "Elastic/FACOps.I"
+#endif
+
+namespace SAMRAI {
+  namespace solv {
+
+    tbox::Pointer<pdat::CellVariable<double> >
+    Elastic::FACOps::s_cell_scratch_var[tbox::Dimension::MAXIMUM_DIMENSION_VALUE];
+
+    tbox::Pointer<pdat::SideVariable<double> >
+    Elastic::FACOps::s_side_scratch_var[tbox::Dimension::MAXIMUM_DIMENSION_VALUE];
+
+    tbox::StartupShutdownManager::Handler
+    Elastic::FACOps::s_finalize_handler(
+                                     0,
+                                     0,
+                                     0,
+                                     Elastic::FACOps::finalizeCallback,
+                                     tbox::StartupShutdownManager::priorityVariables);
+
+    /*
+********************************************************************
+* Constructor.                                                     *
+********************************************************************
+*/
+    Elastic::FACOps::FACOps(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_smoothing_choice("Tackley"),
+      d_coarse_solver_choice(
+#ifdef HAVE_HYPRE
+                             "hypre"
+#else
+                             "Tackley"
+#endif
+
+                             ),
+      d_cf_discretization("Ewing"),
+      p_prolongation_method("P_REFINE"),
+      v_prolongation_method("V_REFINE"),
+      p_rrestriction_method("CONSERVATIVE_COARSEN"),
+      d_coarse_solver_tolerance(1.e-8),
+      d_coarse_solver_max_iterations(10),
+      d_residual_tolerance_during_smoothing(-1.0),
+      cell_moduli_id(invalid_id),
+      edge_moduli_id(invalid_id),
+      dp_id(invalid_id),
+#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(invalid_id),
+      d_side_scratch_id(invalid_id),
+      p_prolongation_refine_operator(),
+      p_prolongation_refine_schedules(),
+      v_prolongation_refine_operator(),
+      v_prolongation_refine_schedules(),
+      p_urestriction_coarsen_operator(),
+      p_urestriction_coarsen_schedules(),
+      v_urestriction_coarsen_operator(),
+      v_urestriction_coarsen_schedules(),
+      p_rrestriction_coarsen_operator(),
+      p_rrestriction_coarsen_schedules(),
+      v_rrestriction_coarsen_operator(),
+      v_rrestriction_coarsen_schedules(),
+      p_ghostfill_refine_operator(),
+      p_ghostfill_refine_schedules(),
+      v_ghostfill_refine_operator(),
+      v_ghostfill_refine_schedules(),
+      p_nocoarse_refine_schedules(),
+      v_nocoarse_refine_schedules(),
+      p_refine_patch_strategy(dim,
+                              d_object_name + "::refine patch strategy"),
+      v_refine_patch_strategy(dim,
+                              d_object_name + "::refine patch strategy"),
+      v_coarsen_patch_strategy(dim,
+                               d_object_name + "::coarsen patch strategy"),
+      d_enable_logging(false),
+      d_preconditioner(NULL),
+      d_hopscell(),
+      d_hopsside()
+    {
+
+      t_restrict_solution = tbox::TimerManager::getManager()->
+        getTimer("solv::Elastic::FACOps::restrictSolution()");
+      t_restrict_residual = tbox::TimerManager::getManager()->
+        getTimer("solv::Elastic::FACOps::restrictResidual()");
+      t_prolong = tbox::TimerManager::getManager()->
+        getTimer("solv::Elastic::FACOps::prolongErrorAndCorrect()");
+      t_smooth_error = tbox::TimerManager::getManager()->
+        getTimer("solv::Elastic::FACOps::smoothError()");
+      t_solve_coarsest = tbox::TimerManager::getManager()->
+        getTimer("solv::Elastic::FACOps::solveCoarsestLevel()");
+      t_compute_composite_residual = tbox::TimerManager::getManager()->
+        getTimer("solv::Elastic::FACOps::computeCompositeResidualOnLevel()");
+      t_compute_residual_norm = tbox::TimerManager::getManager()->
+        getTimer("solv::Elastic::FACOps::computeResidualNorm()");
+
+      if (d_dim == tbox::Dimension(1) || d_dim > tbox::Dimension(3)) {
+        TBOX_ERROR("Elastic::FACOps : 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 << "Elastic::FACOps::private_cell_scratch" << dim.getValue();
+        s_cell_scratch_var[dim.getValue() - 1] = new pdat::CellVariable<double>
+          (dim, ss.str());
+        ss.str("");
+        ss << "Elastic::FACOps::private_side_scratch" << dim.getValue();
+        s_side_scratch_var[dim.getValue() - 1] = new pdat::SideVariable<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_side_scratch_id = vdb->
+        registerVariableAndContext(s_side_scratch_var[dim.getValue() - 1],
+                                   d_context,
+                                   hier::IntVector::getOne(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);
+
+        p_prolongation_method =
+          database->getStringWithDefault("p_prolongation_method",
+                                         p_prolongation_method);
+
+        v_prolongation_method =
+          database->getStringWithDefault("v_prolongation_method",
+                                         v_prolongation_method);
+
+        p_rrestriction_method =
+          database->getStringWithDefault("p_rrestriction_method",
+                                         p_rrestriction_method);
+
+        d_enable_logging =
+          database->getBoolWithDefault("enable_logging",
+                                       d_enable_logging);
+
+      }
+    }
+
+  }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps/computeCompositeResidualOnLevel.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps/computeCompositeResidualOnLevel.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,107 @@
+#include "Elastic/FACOps.h"
+
+void SAMRAI::solv::Elastic::FACOps::computeCompositeResidualOnLevel
+(SAMRAIVectorReal<double>& residual,
+ const SAMRAIVectorReal<double>& solution,
+ const SAMRAIVectorReal<double>& rhs,
+ int ln,
+ bool error_equation_indicator) {
+
+  t_compute_composite_residual->start();
+
+#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 p_id = solution.getComponentDescriptorIndex(0);
+  const int v_id = solution.getComponentDescriptorIndex(1);
+  p_refine_patch_strategy.setTargetDataId(p_id);
+  v_refine_patch_strategy.setTargetDataId(v_id);
+  // v_refine_patch_strategy.setHomogeneousBc(error_equation_indicator);
+
+  /*
+   * 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. */
+
+  set_boundaries(p_id,v_id,ln,error_equation_indicator);
+  if (ln > d_ln_min) {
+    /* Fill from current, next coarser level and physical boundary */
+    xeqScheduleGhostFill(p_id, v_id, ln);
+  } else {
+    /* Fill from current and physical boundary */
+    xeqScheduleGhostFillNoCoarse(p_id, v_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> >
+      p_ptr = solution.getComponentPatchData(0, *patch);
+    tbox::Pointer<pdat::SideData<double> >
+      v_ptr = solution.getComponentPatchData(1, *patch);
+    tbox::Pointer<pdat::CellData<double> >
+      cell_moduli_ptr = patch->getPatchData(cell_moduli_id);
+    tbox::Pointer<pdat::CellData<double> >
+      p_rhs_ptr = rhs.getComponentPatchData(0, *patch);
+    tbox::Pointer<pdat::SideData<double> >
+      v_rhs_ptr = rhs.getComponentPatchData(1, *patch);
+    tbox::Pointer<pdat::CellData<double> >
+      p_resid_ptr = residual.getComponentPatchData(0, *patch);
+    tbox::Pointer<pdat::SideData<double> >
+      v_resid_ptr = residual.getComponentPatchData(1, *patch);
+
+    hier::Box pbox=patch->getBox();
+    pbox.growUpper(hier::IntVector::getOne(d_dim));
+    tbox::Pointer<geom::CartesianPatchGeometry>
+      geom = patch->getPatchGeometry();
+
+    switch(d_dim.getValue())
+      {
+      case 2:
+        residual_2D(*p_ptr,*v_ptr,*cell_moduli_ptr,*p_rhs_ptr,*v_rhs_ptr,
+                    *p_resid_ptr,*v_resid_ptr,*patch,pbox,*geom);
+        break;
+      case 3:
+        residual_3D(*p_ptr,*v_ptr,*cell_moduli_ptr,*p_rhs_ptr,*v_rhs_ptr,
+                    *p_resid_ptr,*v_resid_ptr,*patch,pbox,*geom);
+        break;
+      default:
+        abort();
+      }
+  }
+
+  t_compute_composite_residual->stop();
+}
+
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps/computeResidualNorm.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps/computeResidualNorm.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,33 @@
+#include "Elastic/FACOps.h"
+
+double SAMRAI::solv::Elastic::FACOps::computeResidualNorm
+(const SAMRAIVectorReal<double>& residual,
+ int fine_ln,
+ int coarse_ln)
+{
+  if (coarse_ln != residual.getCoarsestLevelNumber() ||
+      fine_ln != residual.getFinestLevelNumber()) {
+    TBOX_ERROR("Elastic::FACOps::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.
+   *
+   * We use maxNorm because it is a definite upper bound on the error.
+   */
+  double norm = residual.maxNorm();
+  t_compute_residual_norm->stop();
+  return norm;
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps/computeVectorWeights.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps/computeVectorWeights.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,147 @@
+/*************************************************************************
+ *
+ * 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 Elastic using FAC 
+ *
+ ************************************************************************/
+#include "Elastic/FACOps.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 "Elastic/HypreSolver.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"
+
+namespace SAMRAI {
+  namespace solv {
+
+    /*
+********************************************************************
+* Compute the vector weight and put it at a specified patch data   *
+* index.                                                           *
+********************************************************************
+*/
+
+    void Elastic::FACOps::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
+    }
+
+  }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps/deallocateOperatorState.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps/deallocateOperatorState.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,79 @@
+/*************************************************************************
+ *
+ * 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 Elastic using FAC 
+ *
+ ************************************************************************/
+#include "Elastic/FACOps.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 "Elastic/HypreSolver.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"
+
+namespace SAMRAI {
+  namespace solv {
+
+    /*
+********************************************************************
+* FACOperatorStrategy virtual deallocateOperatorState        *
+* function.  Deallocate internal hierarchy-dependent data.         *
+* State is allocated iff hierarchy is set.                         *
+********************************************************************
+*/
+
+    void Elastic::FACOps::deallocateOperatorState()
+    {
+      if (d_hierarchy) {
+        d_cf_boundary.resizeArray(0);
+#ifdef HAVE_HYPRE
+        d_hypre_solver.deallocateSolverState();
+#endif
+        d_hierarchy.setNull();
+        d_ln_min = -1;
+        d_ln_max = -1;
+
+        p_prolongation_refine_schedules.setNull();
+        v_prolongation_refine_schedules.setNull();
+        p_urestriction_coarsen_schedules.setNull();
+        v_urestriction_coarsen_schedules.setNull();
+        p_rrestriction_coarsen_schedules.setNull();
+        v_rrestriction_coarsen_schedules.setNull();
+        p_ghostfill_refine_schedules.setNull();
+        v_ghostfill_refine_schedules.setNull();
+        p_nocoarse_refine_schedules.setNull();
+        v_nocoarse_refine_schedules.setNull();
+      }
+    }
+
+  }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps/finalizeCallback.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps/finalizeCallback.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,56 @@
+/*************************************************************************
+ *
+ * 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 Elastic using FAC 
+ *
+ ************************************************************************/
+#include "Elastic/FACOps.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 "Elastic/HypreSolver.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"
+
+namespace SAMRAI {
+  namespace solv {
+
+    void
+    Elastic::FACOps::finalizeCallback()
+    {
+      for (int d = 0; d < tbox::Dimension::MAXIMUM_DIMENSION_VALUE; ++d) {
+        s_cell_scratch_var[d].setNull();
+        s_side_scratch_var[d].setNull();
+      }
+    }
+
+  }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps/initializeOperatorState.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps/initializeOperatorState.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,469 @@
+/*************************************************************************
+ *
+ * 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 Elastic using FAC 
+ *
+ ************************************************************************/
+#include "Elastic/FACOps.h"
+
+#include "SAMRAI/geom/CartesianGridGeometry.h"
+#include "SAMRAI/xfer/PatchLevelFullFillPattern.h"
+/*
+************************************************************************
+* FACOperatorStrategy virtual initializeOperatorState function.  *
+*                                                                      *
+* Set internal variables to correspond to the solution passed in.      *
+* Look up transfer operators.                                          *
+************************************************************************
+*/
+
+void SAMRAI::solv::Elastic::FACOps::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"
+  //              <<
+  //              "Elastic::FACOps::initializeOperatorState\n"
+  //              << "You must use "
+  //              <<
+  //              "Elastic::FACOps::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);
+  }
+
+  v_coarsen_patch_strategy.coarse_fine=d_cf_boundary;
+// #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_elastic_spec);
+//   }
+// #endif
+
+  /*
+   * Get the transfer operators.
+   * Cell (solution, error, etc) coarsening is conservative.
+   */
+  tbox::Pointer<geom::CartesianGridGeometry> geometry =
+    d_hierarchy->getGridGeometry();
+  tbox::Pointer<hier::Variable> variable;
+
+  vdb->mapIndexToVariable(d_cell_scratch_id, variable);
+  p_prolongation_refine_operator =
+    geometry->lookupRefineOperator(variable,
+                                   p_prolongation_method);
+
+  vdb->mapIndexToVariable(d_side_scratch_id, variable);
+  v_prolongation_refine_operator =
+    geometry->lookupRefineOperator(variable,
+                                   v_prolongation_method);
+
+  vdb->mapIndexToVariable(d_cell_scratch_id, variable);
+  p_urestriction_coarsen_operator =
+    geometry->lookupCoarsenOperator(variable,
+                                    "CONSERVATIVE_COARSEN");
+  p_rrestriction_coarsen_operator =
+    geometry->lookupCoarsenOperator(variable,
+                                   p_rrestriction_method);
+
+  vdb->mapIndexToVariable(d_side_scratch_id, variable);
+  v_urestriction_coarsen_operator =
+    v_rrestriction_coarsen_operator =
+    geometry->lookupCoarsenOperator(variable,
+                                    "V_COARSEN");
+
+  vdb->mapIndexToVariable(d_cell_scratch_id, variable);
+  p_ghostfill_refine_operator =
+    geometry->lookupRefineOperator(variable,
+                                   "P_BOUNDARY_REFINE");
+
+  vdb->mapIndexToVariable(d_side_scratch_id, variable);
+  v_ghostfill_refine_operator =
+    geometry->lookupRefineOperator(variable,
+                                   "V_BOUNDARY_REFINE");
+
+#ifdef DEBUG_CHECK_ASSERTIONS
+  if (!p_prolongation_refine_operator) {
+    TBOX_ERROR(d_object_name
+               << ": Cannot find p prolongation refine operator");
+  }
+  if (!v_prolongation_refine_operator) {
+    TBOX_ERROR(d_object_name
+               << ": Cannot find v prolongation refine operator");
+  }
+  if (!p_urestriction_coarsen_operator) {
+    TBOX_ERROR(d_object_name
+               << ": Cannot find p restriction coarsening operator");
+  }
+  if (!v_urestriction_coarsen_operator) {
+    TBOX_ERROR(d_object_name
+               << ": Cannot find v restriction coarsening operator");
+  }
+  if (!p_rrestriction_coarsen_operator) {
+    TBOX_ERROR(d_object_name
+               << ": Cannot find p restriction coarsening operator");
+  }
+  if (!v_rrestriction_coarsen_operator) {
+    TBOX_ERROR(d_object_name
+               << ": Cannot find v restriction coarsening operator");
+  }
+  if (!p_ghostfill_refine_operator) {
+    TBOX_ERROR(d_object_name
+               << ": Cannot find ghost filling refinement operator");
+  }
+  if (!v_ghostfill_refine_operator) {
+    TBOX_ERROR(d_object_name
+               << ": Cannot find ghost filling refinement operator");
+  }
+#endif
+
+  /*
+   * Make space for saving communication schedules.
+   * There is no need to delete the old schedules first
+   * because we have deallocated the solver state above.
+   */
+  p_prolongation_refine_schedules.resizeArray(d_ln_max + 1);
+  v_prolongation_refine_schedules.resizeArray(d_ln_max + 1);
+  p_ghostfill_refine_schedules.resizeArray(d_ln_max + 1);
+  v_ghostfill_refine_schedules.resizeArray(d_ln_max + 1);
+  p_nocoarse_refine_schedules.resizeArray(d_ln_max + 1);
+  v_nocoarse_refine_schedules.resizeArray(d_ln_max + 1);
+  p_urestriction_coarsen_schedules.resizeArray(d_ln_max + 1);
+  p_rrestriction_coarsen_schedules.resizeArray(d_ln_max + 1);
+  v_urestriction_coarsen_schedules.resizeArray(d_ln_max + 1);
+  v_rrestriction_coarsen_schedules.resizeArray(d_ln_max + 1);
+
+  xfer::RefineAlgorithm p_prolongation_refine_algorithm(d_dim),
+    v_prolongation_refine_algorithm(d_dim),
+    p_ghostfill_refine_algorithm(d_dim),
+    v_ghostfill_refine_algorithm(d_dim),
+    p_nocoarse_refine_algorithm(d_dim),
+    v_nocoarse_refine_algorithm(d_dim);
+  xfer::CoarsenAlgorithm p_urestriction_coarsen_algorithm(d_dim),
+    p_rrestriction_coarsen_algorithm(d_dim),
+    v_urestriction_coarsen_algorithm(d_dim),
+    v_rrestriction_coarsen_algorithm(d_dim);
+
+  /* This is a little confusing.  The only real purpose here is to
+     create a communication schedule.  That communication schedule is
+     then reused later when refining, though with a different source,
+     scratch, and destination.  So the arguments to registerRefine are
+     not all that important, because a different refineAlgorithm will
+     be used then. */
+
+  p_prolongation_refine_algorithm.
+    registerRefine(d_cell_scratch_id,
+                   solution.getComponentDescriptorIndex(0),
+                   d_cell_scratch_id,
+                   p_prolongation_refine_operator);
+  v_prolongation_refine_algorithm.
+    registerRefine(d_side_scratch_id,
+                   solution.getComponentDescriptorIndex(1),
+                   d_side_scratch_id,
+                   v_prolongation_refine_operator);
+  p_urestriction_coarsen_algorithm.
+    registerCoarsen(solution.getComponentDescriptorIndex(0),
+                    solution.getComponentDescriptorIndex(0),
+                    p_urestriction_coarsen_operator);
+  p_rrestriction_coarsen_algorithm.
+    registerCoarsen(rhs.getComponentDescriptorIndex(0),
+                    rhs.getComponentDescriptorIndex(0),
+                    p_rrestriction_coarsen_operator);
+  v_urestriction_coarsen_algorithm.
+    registerCoarsen(solution.getComponentDescriptorIndex(1),
+                    solution.getComponentDescriptorIndex(1),
+                    v_urestriction_coarsen_operator);
+  v_rrestriction_coarsen_algorithm.
+    registerCoarsen(rhs.getComponentDescriptorIndex(1),
+                    rhs.getComponentDescriptorIndex(1),
+                    v_rrestriction_coarsen_operator);
+  p_ghostfill_refine_algorithm.
+    registerRefine(solution.getComponentDescriptorIndex(0),
+                   solution.getComponentDescriptorIndex(0),
+                   solution.getComponentDescriptorIndex(0),
+                   p_ghostfill_refine_operator);
+  v_ghostfill_refine_algorithm.
+    registerRefine(solution.getComponentDescriptorIndex(1),
+                   solution.getComponentDescriptorIndex(1),
+                   solution.getComponentDescriptorIndex(1),
+                   v_ghostfill_refine_operator);
+  p_nocoarse_refine_algorithm.
+    registerRefine(solution.getComponentDescriptorIndex(0),
+                   solution.getComponentDescriptorIndex(0),
+                   solution.getComponentDescriptorIndex(0),
+                   tbox::Pointer<xfer::RefineOperator>(0));
+  v_nocoarse_refine_algorithm.
+    registerRefine(solution.getComponentDescriptorIndex(1),
+                   solution.getComponentDescriptorIndex(1),
+                   solution.getComponentDescriptorIndex(1),
+                   tbox::Pointer<xfer::RefineOperator>(0));
+
+  /* Refinement and ghost fill operators */
+  for (int dest_ln = d_ln_min + 1; dest_ln <= d_ln_max; ++dest_ln) {
+
+    tbox::Pointer<xfer::PatchLevelFullFillPattern>
+      fill_pattern(new xfer::PatchLevelFullFillPattern());
+    p_prolongation_refine_schedules[dest_ln] =
+      p_prolongation_refine_algorithm.
+      createSchedule(fill_pattern,
+                     d_hierarchy->getPatchLevel(dest_ln),
+                     tbox::Pointer<hier::PatchLevel>(),
+                     dest_ln - 1,
+                     d_hierarchy);
+    if (!p_prolongation_refine_schedules[dest_ln]) {
+      TBOX_ERROR(d_object_name
+                 << ": Cannot create a refine schedule for p prolongation!\n");
+    }
+    v_prolongation_refine_schedules[dest_ln] =
+      v_prolongation_refine_algorithm.
+      createSchedule(fill_pattern,
+                     d_hierarchy->getPatchLevel(dest_ln),
+                     tbox::Pointer<hier::PatchLevel>(),
+                     dest_ln - 1,
+                     d_hierarchy);
+    if (!v_prolongation_refine_schedules[dest_ln]) {
+      TBOX_ERROR(d_object_name
+                 << ": Cannot create a refine schedule for v prolongation!\n");
+    }
+    p_ghostfill_refine_schedules[dest_ln] =
+      p_ghostfill_refine_algorithm.
+      createSchedule(d_hierarchy->getPatchLevel(dest_ln),
+                     dest_ln - 1,
+                     d_hierarchy,
+                     &p_refine_patch_strategy);
+    if (!p_ghostfill_refine_schedules[dest_ln]) {
+      TBOX_ERROR(d_object_name
+                 << ": Cannot create a refine schedule for ghost filling!\n");
+    }
+    v_ghostfill_refine_schedules[dest_ln] =
+      v_ghostfill_refine_algorithm.
+      createSchedule(d_hierarchy->getPatchLevel(dest_ln),
+                     dest_ln - 1,
+                     d_hierarchy,
+                     &v_refine_patch_strategy);
+    if (!v_ghostfill_refine_schedules[dest_ln]) {
+      TBOX_ERROR(d_object_name
+                 << ": Cannot create a refine schedule for ghost filling!\n");
+    }
+    p_nocoarse_refine_schedules[dest_ln] =
+      p_nocoarse_refine_algorithm.
+      createSchedule(d_hierarchy->getPatchLevel(dest_ln));
+    if (!p_nocoarse_refine_schedules[dest_ln]) {
+      TBOX_ERROR(d_object_name
+                 << ": Cannot create a refine schedule for ghost filling on bottom level!\n");
+    }
+    v_nocoarse_refine_schedules[dest_ln] =
+      v_nocoarse_refine_algorithm.
+      createSchedule(d_hierarchy->getPatchLevel(dest_ln));
+    if (!v_nocoarse_refine_schedules[dest_ln]) {
+      TBOX_ERROR(d_object_name
+                 << ": Cannot create a refine schedule for ghost filling on bottom level!\n");
+    }
+  }
+
+  /* Coarsening operators */
+  for (int dest_ln = d_ln_min; dest_ln < d_ln_max; ++dest_ln) {
+    p_urestriction_coarsen_schedules[dest_ln] =
+      p_urestriction_coarsen_algorithm.
+      createSchedule(d_hierarchy->getPatchLevel(dest_ln),
+                     d_hierarchy->getPatchLevel(dest_ln + 1));
+    if (!p_urestriction_coarsen_schedules[dest_ln]) {
+      TBOX_ERROR(d_object_name
+                 << ": Cannot create a coarsen schedule for U p restriction!\n");
+    }
+    p_rrestriction_coarsen_schedules[dest_ln] =
+      p_rrestriction_coarsen_algorithm.
+      createSchedule(d_hierarchy->getPatchLevel(dest_ln),
+                     d_hierarchy->getPatchLevel(dest_ln + 1));
+    if (!p_rrestriction_coarsen_schedules[dest_ln]) {
+      TBOX_ERROR(d_object_name
+                 << ": Cannot create a coarsen schedule for R p restriction!\n");
+    }
+
+    v_urestriction_coarsen_schedules[dest_ln] =
+      v_urestriction_coarsen_algorithm.
+      createSchedule(d_hierarchy->getPatchLevel(dest_ln),
+                     d_hierarchy->getPatchLevel(dest_ln + 1),
+                     &v_coarsen_patch_strategy);
+    if (!v_urestriction_coarsen_schedules[dest_ln]) {
+      TBOX_ERROR(d_object_name
+                 << ": Cannot create a coarsen schedule for U v restriction!\n");
+    }
+    v_rrestriction_coarsen_schedules[dest_ln] =
+      v_rrestriction_coarsen_algorithm.
+      createSchedule(d_hierarchy->getPatchLevel(dest_ln),
+                     d_hierarchy->getPatchLevel(dest_ln + 1),
+                     &v_coarsen_patch_strategy);
+    if (!v_rrestriction_coarsen_schedules[dest_ln]) {
+      TBOX_ERROR(d_object_name
+                 << ": Cannot create a coarsen schedule for R v restriction!\n");
+    }
+  }
+
+  /* Ordinary ghost fill operator on the coarsest level */
+  p_nocoarse_refine_schedules[d_ln_min] =
+    p_nocoarse_refine_algorithm.
+    createSchedule(d_hierarchy->getPatchLevel(d_ln_min));
+  if (!p_nocoarse_refine_schedules[d_ln_min]) {
+    TBOX_ERROR(
+               d_object_name
+               <<
+               ": Cannot create a refine schedule for p ghost filling on bottom level!\n");
+  }
+  v_nocoarse_refine_schedules[d_ln_min] =
+    v_nocoarse_refine_algorithm.
+    createSchedule(d_hierarchy->getPatchLevel(d_ln_min));
+  if (!v_nocoarse_refine_schedules[d_ln_min]) {
+    TBOX_ERROR(
+               d_object_name
+               <<
+               ": Cannot create a refine schedule for v ghost filling on bottom level!\n");
+  }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps/postprocessOneCycle.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps/postprocessOneCycle.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,74 @@
+/*************************************************************************
+ *
+ * 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 Elastic using FAC 
+ *
+ ************************************************************************/
+#include "Elastic/FACOps.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 "Elastic/HypreSolver.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"
+
+/*
+********************************************************************
+* FACOperatorStrategy virtual postprocessOneCycle function.  *
+********************************************************************
+*/
+
+void SAMRAI::solv::Elastic::FACOps::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;
+    }
+  }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps/prolongErrorAndCorrect.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps/prolongErrorAndCorrect.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,123 @@
+/*************************************************************************
+ *
+ * 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 Elastic using FAC 
+ *
+ ************************************************************************/
+#include "Elastic/FACOps.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 "Elastic/HypreSolver.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"
+
+/*
+***********************************************************************
+* 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 SAMRAI::solv::Elastic::FACOps::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);
+  fine_level->allocatePatchData(d_side_scratch_id);
+
+  // int p_src(s.getComponentDescriptorIndex(0)),
+  //   v_src(s.getComponentDescriptorIndex(1)),
+  //   p_dst(d.getComponentDescriptorIndex(0)),
+  //   v_dst(d.getComponentDescriptorIndex(1));
+  // xeqScheduleGhostFillNoCoarse(invalid_id,v_src,dest_ln+1);
+
+  /*
+   * 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.
+   */
+  p_refine_patch_strategy.setTargetDataId(d_cell_scratch_id);
+  v_refine_patch_strategy.setTargetDataId(d_side_scratch_id);
+  // v_refine_patch_strategy.setHomogeneousBc(true);
+  xeqScheduleProlongation(d_cell_scratch_id,
+                          s.getComponentDescriptorIndex(0),
+                          d_cell_scratch_id,
+                          d_side_scratch_id,
+                          s.getComponentDescriptorIndex(1),
+                          d_side_scratch_id,
+                          dest_ln);
+
+  set_boundaries(s.getComponentDescriptorIndex(0),
+                 s.getComponentDescriptorIndex(1),fine_level,true);
+  /*
+   * 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 p_dst = d.getComponentDescriptorIndex(0);
+    hierarchy_math_ops.add(p_dst, p_dst, d_cell_scratch_id);
+  }
+  {
+    math::HierarchySideDataOpsReal<double>
+      hierarchy_math_ops(d_hierarchy, dest_ln, dest_ln);
+    const int v_dst = d.getComponentDescriptorIndex(1);
+    hierarchy_math_ops.add(v_dst, v_dst, d_side_scratch_id);
+  }
+  fine_level->deallocatePatchData(d_cell_scratch_id);
+  fine_level->deallocatePatchData(d_side_scratch_id);
+
+  t_prolong->stop();
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps/residual_2D.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps/residual_2D.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,83 @@
+#include "Elastic/FACOps.h"
+#include "Constants.h"
+
+void SAMRAI::solv::Elastic::FACOps::residual_2D
+(pdat::CellData<double> &p,
+ pdat::SideData<double> &v,
+ pdat::CellData<double> &cell_moduli,
+ pdat::CellData<double> &p_rhs,
+ pdat::SideData<double> &v_rhs,
+ pdat::CellData<double> &p_resid,
+ pdat::SideData<double> &v_resid,
+ hier::Patch &patch,
+ const hier::Box &pbox,
+ const geom::CartesianPatchGeometry &geom)
+{
+  const hier::Index ip(1,0), jp(0,1);
+
+  tbox::Pointer<pdat::NodeData<double> >
+    edge_moduli_ptr = patch.getPatchData(edge_moduli_id);
+  pdat::NodeData<double> &edge_moduli(*edge_moduli_ptr);
+
+  double dx = geom.getDx()[0];
+  double dy = geom.getDx()[1];
+
+  for(pdat::CellIterator ci(pbox); ci; ci++)
+    {
+      pdat::CellIndex center(*ci);
+      pdat::CellIndex up(center), down(center), right(center),
+        left(center);
+
+      ++up[1];
+      --down[1];
+      ++right[0];
+      --left[0];
+
+      const pdat::SideIndex
+        x(center,0,pdat::SideIndex::Lower),
+        y(center,1,pdat::SideIndex::Lower);
+      const pdat::NodeIndex
+        edge(center,pdat::NodeIndex::LowerLeft);
+
+      /* p */
+      if(center[0]!=pbox.upper(0) && center[1]!=pbox.upper(1))
+        {
+          p_resid(center)=0;
+        }
+
+      /* vx */
+      if(center[1]!=pbox.upper(1))
+        {
+          /* If x==0 */
+          if((center[0]==pbox.lower(0) && v(x-ip)==boundary_value)
+             || (center[0]==pbox.upper(0) && v(x+ip)==boundary_value))
+            {
+              v_resid(x)=0;
+            }
+          else
+            {
+              v_resid(x)=v_rhs(x)
+                - v_operator_2D(v,cell_moduli,edge_moduli,center,
+                                edge,x,y,ip,jp,dx,dy);
+            }
+        }
+
+      /* vy */
+      if(center[0]!=pbox.upper(0))
+        {
+          /* If y==0 */
+          if((center[1]==pbox.lower(1) && v(y-jp)==boundary_value)
+             || (center[1]==pbox.upper(1) && v(y+jp)==boundary_value))
+            {
+              v_resid(y)=0;
+            }
+          else
+            {
+              v_resid(y)=v_rhs(y)
+                - v_operator_2D(v,cell_moduli,edge_moduli,center,
+                                edge,y,x,jp,ip,dy,dx);
+            }
+        }
+    }
+}
+
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps/residual_3D.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps/residual_3D.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,73 @@
+#include "Elastic/FACOps.h"
+#include "Constants.h"
+
+void SAMRAI::solv::Elastic::FACOps::residual_3D
+(pdat::CellData<double> &p,
+ pdat::SideData<double> &v,
+ pdat::CellData<double> &cell_moduli,
+ pdat::CellData<double> &p_rhs,
+ pdat::SideData<double> &v_rhs,
+ pdat::CellData<double> &p_resid,
+ pdat::SideData<double> &v_resid,
+ hier::Patch &patch,
+ const hier::Box &pbox,
+ const geom::CartesianPatchGeometry &geom)
+{
+  tbox::Pointer<pdat::EdgeData<double> >
+    edge_moduli_ptr = patch.getPatchData(edge_moduli_id);
+  pdat::EdgeData<double> &edge_moduli(*edge_moduli_ptr);
+
+  const double *Dx = geom.getDx();
+  const hier::Index ip(1,0,0), jp(0,1,0), kp(0,0,1);
+  const hier::Index pp[]={ip,jp,kp};
+
+  for(pdat::CellIterator ci(pbox); ci; ci++)
+    {
+      pdat::CellIndex center(*ci);
+      pdat::CellIndex up(center), down(center), right(center),
+        left(center), front(center), back(center);
+
+      ++right[0];
+      --left[0];
+      ++up[1];
+      --down[1];
+      ++front[2];
+      --back[2];
+
+      /* p */
+      if(center[0]!=pbox.upper(0) && center[1]!=pbox.upper(1)
+         && center[2]!=pbox.upper(2))
+        {
+          p_resid(center)=0;
+        }
+
+      for(int ix=0;ix<3;++ix)
+        {
+          const int iy((ix+1)%3), iz((ix+2)%3);
+          const pdat::SideIndex
+            x(center,ix,pdat::SideIndex::Lower),
+            y(center,iy,pdat::SideIndex::Lower),
+            z(center,iz,pdat::SideIndex::Lower);
+          const pdat::EdgeIndex
+            edge_y(center,iy,pdat::EdgeIndex::LowerLeft),
+            edge_z(center,iz,pdat::EdgeIndex::LowerLeft);
+
+          if(center[iy]!=pbox.upper(iy) && center[iz]!=pbox.upper(iz))
+            {
+              if((center[ix]==pbox.lower(ix) && v(x-pp[ix])==boundary_value)
+                 || (center[ix]==pbox.upper(ix) && v(x+pp[ix])==boundary_value))
+                {
+                  v_resid(x)=0;
+                }
+              else
+                {
+                  v_resid(x)=v_rhs(x)
+                    - v_operator_3D(v,cell_moduli,edge_moduli,
+                                    center,edge_y,edge_z,x,y,z,
+                                    pp[ix],pp[iy],pp[iz],Dx[ix],Dx[iy],Dx[iz]);
+                }
+            }
+        }          
+    }
+}
+
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps/restrictResidual.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps/restrictResidual.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,68 @@
+/*************************************************************************
+ *
+ * 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 Elastic using FAC 
+ *
+ ************************************************************************/
+#include "Elastic/FACOps.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 "Elastic/HypreSolver.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"
+
+/*
+********************************************************************
+* FACOperatorStrategy virtual restrictresidual function.     *
+********************************************************************
+*/
+
+void SAMRAI::solv::Elastic::FACOps::restrictResidual
+(const SAMRAIVectorReal<double>& s,
+ SAMRAIVectorReal<double>& d,
+ int dest_ln)
+{
+  t_restrict_residual->start();
+
+  int p_src(s.getComponentDescriptorIndex(0)),
+    p_dst(d.getComponentDescriptorIndex(0)),
+    v_src(s.getComponentDescriptorIndex(1)),
+    v_dst(d.getComponentDescriptorIndex(1));
+
+  /* Need to do a sync because the coarsening for v uses ghost zones */
+  v_coarsen_patch_strategy.setSourceDataId(v_src);
+  xeqScheduleGhostFillNoCoarse(invalid_id,v_src,dest_ln+1);
+
+  xeqScheduleRRestriction(p_dst,p_src,v_dst,v_src,dest_ln);
+
+  t_restrict_residual->stop();
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps/restrictSolution.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps/restrictSolution.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,82 @@
+/*************************************************************************
+ *
+ * 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 Elastic using FAC 
+ *
+ ************************************************************************/
+#include "Elastic/FACOps.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 "Elastic/HypreSolver.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"
+
+/*
+********************************************************************
+* FACOperatorStrategy virtual restrictSolution function.     *
+* After restricting solution, update ghost cells of the affected   *
+* level.                                                           *
+********************************************************************
+*/
+
+void SAMRAI::solv::Elastic::FACOps::restrictSolution
+(const SAMRAIVectorReal<double>& s,
+ SAMRAIVectorReal<double>& d,
+ int dest_ln)
+{
+  t_restrict_solution->start();
+
+  int p_src(s.getComponentDescriptorIndex(0)),
+    p_dst(d.getComponentDescriptorIndex(0)),
+    v_src(s.getComponentDescriptorIndex(1)),
+    v_dst(d.getComponentDescriptorIndex(1));
+
+  /* Need to do a sync because the coarsening for v uses ghost zones. */
+  v_coarsen_patch_strategy.setSourceDataId(v_src);
+  xeqScheduleGhostFillNoCoarse(invalid_id,v_src,dest_ln+1);
+
+  xeqScheduleURestriction(p_dst,p_src,v_dst,v_src,dest_ln);
+
+  tbox::Pointer<hier::PatchLevel> level = d_hierarchy->getPatchLevel(dest_ln);
+  set_boundaries(p_dst,v_dst,level,false);
+  // v_refine_patch_strategy.setHomogeneousBc(false);
+  p_refine_patch_strategy.setTargetDataId(d.getComponentDescriptorIndex(0));
+  v_refine_patch_strategy.setTargetDataId(d.getComponentDescriptorIndex(1));
+
+  if (dest_ln == d_ln_min) {
+    xeqScheduleGhostFillNoCoarse(p_dst,v_dst,dest_ln);
+  } else {
+    xeqScheduleGhostFill(p_dst,v_dst,dest_ln);
+  }
+
+  t_restrict_solution->stop();
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps/set_boundaries.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps/set_boundaries.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,57 @@
+/*************************************************************************
+ *
+ * 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 Elastic using FAC 
+ *
+ ************************************************************************/
+#include "Elastic/FACOps.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 "Elastic/HypreSolver.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"
+
+#include "Constants.h"
+#include "Elastic/set_boundary.h"
+
+/* Set the physical boundaries for the velocity. */
+
+void SAMRAI::solv::Elastic::FACOps::set_boundaries
+(const int &p_id, const int &v_id,
+ tbox::Pointer<hier::PatchLevel> &level, const bool &rhs)
+{
+  for (hier::PatchLevel::Iterator pi(*level); pi; pi++)
+    {
+      tbox::Pointer<hier::Patch> patch = *pi;
+      set_boundary(*patch,p_id,v_id,rhs);
+    }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps/smoothError.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps/smoothError.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,72 @@
+/*************************************************************************
+ *
+ * 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 Elastic using FAC 
+ *
+ ************************************************************************/
+#include "Elastic/FACOps.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 "Elastic/HypreSolver.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"
+
+/*
+********************************************************************
+********************************************************************
+*/
+
+void SAMRAI::solv::Elastic::FACOps::smoothError
+(SAMRAIVectorReal<double>& data,
+ const SAMRAIVectorReal<double>& residual,
+ int ln,
+ int num_sweeps)
+{
+  t_smooth_error->start();
+
+  if (d_smoothing_choice == "Tackley") {
+    if(d_dim.getValue()==2)
+      smooth_Tackley_2D(data,residual,ln,num_sweeps,
+                        d_residual_tolerance_during_smoothing);
+    else if(d_dim.getValue()==3)
+      smooth_Tackley_3D(data,residual,ln,num_sweeps,
+                        d_residual_tolerance_during_smoothing);
+    else
+	TBOX_ERROR(d_object_name << ": Invalid dimension in Elastic::FACOps.");
+  } else {
+    TBOX_ERROR(d_object_name << ": Bad smoothing choice '"
+               << d_smoothing_choice
+               << "' in Elastic::FACOps.");
+  }
+
+  t_smooth_error->stop();
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps/smooth_Tackley_2D.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps/smooth_Tackley_2D.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,200 @@
+#include "Elastic/FACOps.h"
+#include "Constants.h"
+#include "Elastic/dRc_dp.h"
+/*
+********************************************************************
+* Workhorse function to smooth error using red-black               *
+* Gauss-Seidel iterations.                                         *
+********************************************************************
+*/
+
+void SAMRAI::solv::Elastic::FACOps::smooth_Tackley_2D
+(SAMRAIVectorReal<double>& solution,
+ const SAMRAIVectorReal<double>& residual,
+ int ln,
+ int num_sweeps,
+ double residual_tolerance)
+{
+  const int p_id(solution.getComponentDescriptorIndex(0)),
+    p_rhs_id(residual.getComponentDescriptorIndex(0)),
+    v_id(solution.getComponentDescriptorIndex(1)),
+    v_rhs_id(residual.getComponentDescriptorIndex(1));
+
+#ifdef DEBUG_CHECK_ASSERTIONS
+  if (solution.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);
+
+  /* Only need to sync the rhs once. This sync is needed because
+     calculating a new pressure update requires computing in the ghost
+     region so that the update for the velocity inside the box will be
+     correct. */
+  p_refine_patch_strategy.setTargetDataId(p_id);
+  v_refine_patch_strategy.setTargetDataId(v_id);
+  set_boundaries(p_id,v_id,level,true);
+  xeqScheduleGhostFillNoCoarse(p_rhs_id,v_rhs_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(p_id, v_id, ln);
+  }
+
+  double theta_momentum=1.0;
+
+  /*
+   * Smooth the number of sweeps specified or until
+   * the convergence is satisfactory.
+   */
+  double maxres;
+  /*
+   * Instead of checking residual convergence globally, we check the
+   * converged flag.  This avoids possible round-off errors affecting
+   * different processes differently, leading to disagreement on
+   * whether to continue smoothing.
+   */
+  const hier::Index ip(1,0), jp(0,1);
+  bool converged = false;
+  for (int sweep=0; sweep < num_sweeps*(1<<(d_ln_max-ln)) && !converged;
+       ++sweep)
+    {
+      maxres=0;
+
+      /* vx sweep */
+      xeqScheduleGhostFillNoCoarse(p_id,invalid_id,ln);
+      for(int rb=0;rb<2;++rb)
+        {
+          xeqScheduleGhostFillNoCoarse(invalid_id,v_id,ln);
+          for (hier::PatchLevel::Iterator pi(*level); pi; pi++)
+            {
+              tbox::Pointer<hier::Patch> patch = *pi;
+
+              tbox::Pointer<pdat::CellData<double> > p_ptr =
+                patch->getPatchData(p_id);
+              pdat::CellData<double> &p(*p_ptr);
+                
+              tbox::Pointer<pdat::SideData<double> > v_ptr =
+                patch->getPatchData(v_id);
+              pdat::SideData<double> &v(*v_ptr);
+              tbox::Pointer<pdat::SideData<double> > v_rhs_ptr =
+                patch->getPatchData(v_rhs_id);
+              pdat::SideData<double> &v_rhs(*v_rhs_ptr);
+                
+              tbox::Pointer<pdat::CellData<double> > cell_visc_ptr
+                = patch->getPatchData(cell_moduli_id);
+              pdat::CellData<double> &cell_moduli(*cell_visc_ptr);
+              tbox::Pointer<pdat::NodeData<double> > edge_visc_ptr
+                = patch->getPatchData(edge_moduli_id);
+              pdat::NodeData<double> &edge_moduli(*edge_visc_ptr);
+
+              hier::Box pbox=patch->getBox();
+              tbox::Pointer<geom::CartesianPatchGeometry>
+                geom = patch->getPatchGeometry();
+              double dx = geom->getDx()[0];
+              double dy = geom->getDx()[1];
+
+              for(int j=pbox.lower(1); j<=pbox.upper(1); ++j)
+                {
+                  /* Do the red-black skip */
+                  int i_min=pbox.lower(0) + (abs(pbox.lower(0) + j + rb))%2;
+                  for(int i=i_min; i<=pbox.upper(0)+1; i+=2)
+                    {
+                      pdat::CellIndex center(tbox::Dimension(2));
+                      center[0]=i;
+                      center[1]=j;
+
+                      /* Update v */
+                      smooth_V_2D(0,pbox,geom,center,ip,jp,
+                                  v,v_rhs,maxres,dx,dy,cell_moduli,
+                                  edge_moduli,theta_momentum);
+                    }
+                }
+            }
+          set_boundaries(invalid_id,v_id,level,true);
+        }
+
+
+      /* vy sweep */
+
+      for(int rb=0;rb<2;++rb)
+        {
+          xeqScheduleGhostFillNoCoarse(invalid_id,v_id,ln);
+          for (hier::PatchLevel::Iterator pi(*level); pi; pi++)
+            {
+              tbox::Pointer<hier::Patch> patch = *pi;
+
+              tbox::Pointer<pdat::CellData<double> > p_ptr =
+                patch->getPatchData(p_id);
+              pdat::CellData<double> &p(*p_ptr);
+                
+              tbox::Pointer<pdat::SideData<double> > v_ptr =
+                patch->getPatchData(v_id);
+              pdat::SideData<double> &v(*v_ptr);
+              tbox::Pointer<pdat::SideData<double> > v_rhs_ptr =
+                patch->getPatchData(v_rhs_id);
+              pdat::SideData<double> &v_rhs(*v_rhs_ptr);
+                
+              tbox::Pointer<pdat::CellData<double> > cell_visc_ptr
+                = patch->getPatchData(cell_moduli_id);
+              pdat::CellData<double> &cell_moduli(*cell_visc_ptr);
+              tbox::Pointer<pdat::NodeData<double> > edge_visc_ptr
+                = patch->getPatchData(edge_moduli_id);
+              pdat::NodeData<double> &edge_moduli(*edge_visc_ptr);
+
+              hier::Box pbox=patch->getBox();
+              tbox::Pointer<geom::CartesianPatchGeometry>
+                geom = patch->getPatchGeometry();
+              double dx = geom->getDx()[0];
+              double dy = geom->getDx()[1];
+
+              for(int j=pbox.lower(1); j<=pbox.upper(1)+1; ++j)
+                {
+                  /* Do the red-black skip */
+                  int i_min=pbox.lower(0) + (abs(pbox.lower(0) + j + rb))%2;
+                  for(int i=i_min; i<=pbox.upper(0); i+=2)
+                    {
+                      pdat::CellIndex center(tbox::Dimension(2));
+                      center[0]=i;
+                      center[1]=j;
+
+                      /* Update v */
+                      smooth_V_2D(1,pbox,geom,center,jp,ip,
+                                  v,v_rhs,maxres,dy,dx,cell_moduli,
+                                  edge_moduli,theta_momentum);
+                    }
+                }
+            }
+          set_boundaries(invalid_id,v_id,level,true);
+        }
+
+      // 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).
+         */
+        converged = maxres < residual_tolerance;
+        const tbox::SAMRAI_MPI&
+          mpi(d_hierarchy->getDomainMappedBoxLevel().getMPI());
+        int tmp= converged ? 1 : 0;
+        if (mpi.getSize() > 1)
+          {
+            mpi.AllReduce(&tmp, 1, MPI_MIN);
+          }
+        converged=(tmp==1);
+        // if (d_enable_logging)
+        //   tbox::plog
+        //     // << d_object_name << "\n"
+        //     << "Tackley  " << ln << " " << sweep << " : " << maxres << "\n";
+      // }
+    }
+}
+
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps/smooth_Tackley_3D.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps/smooth_Tackley_3D.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,148 @@
+#include "Elastic/FACOps.h"
+#include "Constants.h"
+#include "Elastic/dRc_dp.h"
+/*
+********************************************************************
+* Workhorse function to smooth error using red-black               *
+* Gauss-Seidel iterations.                                         *
+********************************************************************
+*/
+
+void SAMRAI::solv::Elastic::FACOps::smooth_Tackley_3D
+(SAMRAIVectorReal<double>& solution,
+ const SAMRAIVectorReal<double>& residual,
+ int ln,
+ int num_sweeps,
+ double residual_tolerance)
+{
+  const int p_id(solution.getComponentDescriptorIndex(0)),
+    p_rhs_id(residual.getComponentDescriptorIndex(0)),
+    v_id(solution.getComponentDescriptorIndex(1)),
+    v_rhs_id(residual.getComponentDescriptorIndex(1));
+
+#ifdef DEBUG_CHECK_ASSERTIONS
+  if (solution.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);
+
+  /* Only need to sync the rhs once. This sync is needed because
+     calculating a new pressure update requires computing in the ghost
+     region so that the update for the velocity inside the box will be
+     correct. */
+  p_refine_patch_strategy.setTargetDataId(p_id);
+  v_refine_patch_strategy.setTargetDataId(v_id);
+  set_boundaries(p_id,v_id,level,true);
+  xeqScheduleGhostFillNoCoarse(p_rhs_id,v_rhs_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(p_id, v_id, ln);
+  }
+
+  double theta_momentum=1.0;
+
+  /*
+   * Smooth the number of sweeps specified or until
+   * the convergence is satisfactory.
+   */
+  double maxres;
+  /*
+   * Instead of checking residual convergence globally, we check the
+   * converged flag.  This avoids possible round-off errors affecting
+   * different processes differently, leading to disagreement on
+   * whether to continue smoothing.
+   */
+  const hier::Index ip(1,0,0), jp(0,1,0), kp(0,0,1);
+  const hier::Index pp[]={ip,jp,kp};
+  bool converged = false;
+  for (int sweep=0; sweep < num_sweeps*(1<<(2*(d_ln_max-ln))) && !converged;
+       ++sweep)
+    {
+      maxres=0;
+
+      /* v sweeps */
+      xeqScheduleGhostFillNoCoarse(p_id,invalid_id,ln);
+
+      for(int ix=0;ix<3;++ix)
+        for(int rb=0;rb<2;++rb)
+          {
+            xeqScheduleGhostFillNoCoarse(invalid_id,v_id,ln);
+            for (hier::PatchLevel::Iterator pi(*level); pi; pi++)
+              {
+                tbox::Pointer<hier::Patch> patch = *pi;
+
+                tbox::Pointer<pdat::CellData<double> > p_ptr =
+                  patch->getPatchData(p_id);
+                pdat::CellData<double> &p(*p_ptr);
+                
+                tbox::Pointer<pdat::SideData<double> > v_ptr =
+                  patch->getPatchData(v_id);
+                pdat::SideData<double> &v(*v_ptr);
+                tbox::Pointer<pdat::SideData<double> > v_rhs_ptr =
+                  patch->getPatchData(v_rhs_id);
+                pdat::SideData<double> &v_rhs(*v_rhs_ptr);
+                
+                tbox::Pointer<pdat::CellData<double> > cell_visc_ptr
+                  = patch->getPatchData(cell_moduli_id);
+                pdat::CellData<double> &cell_moduli(*cell_visc_ptr);
+                tbox::Pointer<pdat::EdgeData<double> > edge_visc_ptr
+                  = patch->getPatchData(edge_moduli_id);
+                pdat::EdgeData<double> &edge_moduli(*edge_visc_ptr);
+
+                hier::Box pbox=patch->getBox();
+                tbox::Pointer<geom::CartesianPatchGeometry>
+                  geom = patch->getPatchGeometry();
+                const double *Dx = geom->getDx();
+
+                for(int k=pbox.lower(2); k<=pbox.upper(2)+pp[ix][2]; ++k)
+                  for(int j=pbox.lower(1); j<=pbox.upper(1)+pp[ix][1]; ++j)
+                    {
+                      /* Do the red-black skip */
+                      int i_min=pbox.lower(0)
+                        + (abs(pbox.lower(0) + j + k + rb))%2;
+                      for(int i=i_min; i<=pbox.upper(0)+pp[ix][0]; i+=2)
+                        {
+                          pdat::CellIndex center(hier::Index(i,j,k));
+
+                          /* Update v */
+                          smooth_V_3D(ix,pbox,geom,v,v_rhs,cell_moduli,
+                                      edge_moduli,center,
+                                      Dx,theta_momentum,pp,maxres);
+                        }
+                    }
+              }
+            set_boundaries(invalid_id,v_id,level,true);
+          }
+
+      // 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).
+         */
+        converged = maxres < residual_tolerance;
+        const tbox::SAMRAI_MPI&
+          mpi(d_hierarchy->getDomainMappedBoxLevel().getMPI());
+        int tmp= converged ? 1 : 0;
+        if (mpi.getSize() > 1)
+          {
+            mpi.AllReduce(&tmp, 1, MPI_MIN);
+          }
+        converged=(tmp==1);
+        // if (d_enable_logging)
+        //   tbox::plog
+        //     // << d_object_name << "\n"
+        //     << "Tackley  " << ln << " " << sweep << " : " << maxres << "\n";
+      // }
+    }
+}
+
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps/smooth_V_2D.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps/smooth_V_2D.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,79 @@
+#include "Elastic/FACOps.h"
+#include "Constants.h"
+#include "Elastic/dRm_dv.h"
+/*
+********************************************************************
+* Updates one component of the velocity during a red-black *
+* Gauss-Seidel iteration.  *
+********************************************************************
+*/
+void SAMRAI::solv::Elastic::FACOps::smooth_V_2D
+(const int &axis,
+ const hier::Box &pbox,
+ tbox::Pointer<geom::CartesianPatchGeometry> &geom,
+ const pdat::CellIndex &center,
+ const hier::Index &ip,
+ const hier::Index &jp,
+ pdat::SideData<double> &v,
+ pdat::SideData<double> &v_rhs,
+ double &maxres,
+ const double &dx,
+ const double &dy,
+ pdat::CellData<double> &cell_moduli,
+ pdat::NodeData<double> &edge_moduli,
+ const double &theta_momentum)
+{
+  const int off_axis=(axis==0) ? 1 : 0;
+
+  const pdat::SideIndex x(center,axis,pdat::SideIndex::Lower),
+    y(center,off_axis,pdat::SideIndex::Lower);
+  const pdat::NodeIndex edge(center,pdat::NodeIndex::LowerLeft);
+    
+  /* If at a Dirichlet 'x' boundary, leave vx as is */
+  if(!((center[axis]==pbox.lower(axis) && v(x-ip)==boundary_value)
+       || (center[axis]==pbox.upper(axis)+1 && v(x+ip)==boundary_value)))
+    {
+      /* If at the boundary, set things up so that the derivative does
+         not change. */
+      hier::Index offset(0,0);
+      offset[axis]=2;
+      bool set_lower_boundary(false), set_upper_boundary(false);
+      double dv_lower(0), dv_upper(0);
+      if(center[axis]==pbox.lower(axis)+1
+         && !geom->getTouchesRegularBoundary(axis,0))
+        {
+          set_lower_boundary=true;
+          dv_lower=v(x-offset) - v(x);
+        }
+      if(center[axis]==pbox.upper(axis)
+         && !geom->getTouchesRegularBoundary(axis,1))
+        {
+          set_upper_boundary=true;
+          dv_upper=v(x+offset) - v(x);
+        }
+
+      double C_vx=dRm_dv_2D(cell_moduli,edge_moduli,center,center-ip,
+                            edge+jp,edge,dx,dy);
+
+      double delta_Rx=v_rhs(x)
+        - v_operator_2D(v,cell_moduli,edge_moduli,center,
+                        edge,x,y,ip,jp,dx,dy);
+
+      /* No scaling here, though there should be. */
+      maxres=std::max(maxres,std::fabs(delta_Rx));
+
+      v(x)+=delta_Rx*theta_momentum/C_vx;
+
+      /* Set the boundary elements so that the derivative is
+         unchanged. */
+      if(set_lower_boundary)
+        {
+          v(x-offset)=v(x) + dv_lower;
+        }
+      if(set_upper_boundary)
+        {
+          v(x+offset)=v(x) + dv_upper;
+        }
+    }
+}
+
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps/smooth_V_3D.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps/smooth_V_3D.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,78 @@
+#include "Elastic/FACOps.h"
+#include "Constants.h"
+#include "Elastic/dRc_dp.h"
+/*
+********************************************************************
+* Updates one component of the velocity during a red-black *
+* Gauss-Seidel iteration.  *
+********************************************************************
+*/
+void SAMRAI::solv::Elastic::FACOps::smooth_V_3D
+(const int &ix,
+ const hier::Box &pbox,
+ tbox::Pointer<geom::CartesianPatchGeometry> &geom,
+ pdat::SideData<double> &v,
+ pdat::SideData<double> &v_rhs,
+ pdat::CellData<double> &cell_moduli,
+ pdat::EdgeData<double> &edge_moduli,
+ const pdat::CellIndex &center,
+ const double Dx[3],
+ const double &theta_momentum,
+ const hier::Index pp[3],
+ double &maxres)
+{
+  const int iy((ix+1)%3), iz((ix+2)%3);
+  const pdat::SideIndex x(center,ix,pdat::SideIndex::Lower),
+    y(center,iy,pdat::SideIndex::Lower),
+    z(center,iz,pdat::SideIndex::Lower);
+  const pdat::EdgeIndex edge_y(center,iy,pdat::EdgeIndex::LowerLeft),
+    edge_z(center,iz,pdat::EdgeIndex::LowerLeft);
+    
+  /* If at a Dirichlet 'x' boundary, leave vx as is */
+  if(!((center[ix]==pbox.lower(ix) && v(x-pp[ix])==boundary_value)
+       || (center[ix]==pbox.upper(ix)+1 && v(x+pp[ix])==boundary_value)))
+    {
+      /* If at the boundary, set things up so that the derivative does
+         not change. */
+      hier::Index offset(0,0,0);
+      offset[ix]=2;
+      bool set_lower_boundary(false), set_upper_boundary(false);
+      double dv_lower(0), dv_upper(0);
+      if(center[ix]==pbox.lower(ix)+1
+         && !geom->getTouchesRegularBoundary(ix,0))
+        {
+          set_lower_boundary=true;
+          dv_lower=v(x-offset) - v(x);
+        }
+      if(center[ix]==pbox.upper(ix) && !geom->getTouchesRegularBoundary(ix,1))
+        {
+          set_upper_boundary=true;
+          dv_upper=v(x+offset) - v(x);
+        }
+
+      double C_vx=dRm_dv_3D(cell_moduli,edge_moduli,center,center-pp[ix],
+                            edge_y+pp[iz],edge_y,edge_z+pp[iy],edge_z,
+                            Dx[ix],Dx[iy],Dx[iz]);
+
+      double delta_Rx=v_rhs(x)
+        - v_operator_3D(v,cell_moduli,edge_moduli,center,edge_y,edge_z,
+                        x,y,z,pp[ix],pp[iy],pp[iz],Dx[ix],Dx[iy],Dx[iz]);
+
+      /* No scaling here, though there should be. */
+      maxres=std::max(maxres,std::fabs(delta_Rx));
+
+      v(x)+=delta_Rx*theta_momentum/C_vx;
+
+      /* Set the boundary elements so that the derivative is
+         unchanged. */
+      if(set_lower_boundary)
+        {
+          v(x-offset)=v(x) + dv_lower;
+        }
+      if(set_upper_boundary)
+        {
+          v(x+offset)=v(x) + dv_upper;
+        }
+    }
+}
+
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps/solveCoarsestLevel.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps/solveCoarsestLevel.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,90 @@
+/*************************************************************************
+ *
+ * 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 Elastic using FAC 
+ *
+ ************************************************************************/
+#include "Elastic/FACOps.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 "Elastic/HypreSolver.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"
+
+/*
+********************************************************************
+* FACOperatorStrategy virtual solveCoarsestLevel             *
+* function                                                         *
+********************************************************************
+*/
+
+int SAMRAI::solv::Elastic::FACOps::solveCoarsestLevel
+(SAMRAIVectorReal<double>& data,
+ const SAMRAIVectorReal<double>& residual,
+ int coarsest_ln)
+{
+  t_solve_coarsest->start();
+
+  int return_value = 0;
+
+  if (d_coarse_solver_choice == "Tackley"
+      || d_coarse_solver_choice == "Gerya") {
+    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 "
+               << "Elastic::FACOps::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 Elastic::FACOps::solveCoarsestLevel.");
+  }
+
+  xeqScheduleGhostFillNoCoarse(data.getComponentDescriptorIndex(0),
+                               data.getComponentDescriptorIndex(1),
+                               coarsest_ln);
+  t_solve_coarsest->stop();
+
+  return return_value;
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps/solveCoarsestLevel_HYPRE.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps/solveCoarsestLevel_HYPRE.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,96 @@
+/*************************************************************************
+ *
+ * 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 Elastic using FAC 
+ *
+ ************************************************************************/
+#include "Elastic/FACOps.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 "Elastic/HypreSolver.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"
+
+namespace SAMRAI {
+  namespace solv {
+
+#ifdef HAVE_HYPRE
+    /*
+********************************************************************
+* Solve coarsest level using Hypre                                 *
+* We only solve for the error, so we always use homogeneous bc.    *
+********************************************************************
+*/
+
+    int Elastic::FACOps::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 "
+                 << "Elastic::FACOps::solveCoarsestLevel.");
+
+      return 0;
+
+#else
+
+      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
+
+  }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps/xeqScheduleGhostFill.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps/xeqScheduleGhostFill.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,38 @@
+/*************************************************************************
+ *
+ * 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 Elastic using FAC 
+ *
+ ************************************************************************/
+#include "Elastic/FACOps.h"
+
+void SAMRAI::solv::Elastic::FACOps::xeqScheduleGhostFill(int p_id, int v_id,
+                                                      int dest_ln)
+{
+  /* p */
+  {
+    if (!p_ghostfill_refine_schedules[dest_ln]) {
+      TBOX_ERROR("Expected schedule not found.");
+    }
+    xfer::RefineAlgorithm refiner(d_dim);
+    refiner.registerRefine(p_id,p_id,p_id,p_ghostfill_refine_operator);
+    refiner.resetSchedule(p_ghostfill_refine_schedules[dest_ln]);
+    p_ghostfill_refine_schedules[dest_ln]->fillData(0.0,false);
+  }
+
+  /* v */
+  {
+    if (!v_ghostfill_refine_schedules[dest_ln]) {
+      TBOX_ERROR("Expected schedule not found.");
+    }
+    set_boundaries(invalid_id,v_id,dest_ln-1);
+    xfer::RefineAlgorithm refiner(d_dim);
+    refiner.registerRefine(v_id,v_id,v_id,v_ghostfill_refine_operator);
+    refiner.resetSchedule(v_ghostfill_refine_schedules[dest_ln]);
+    v_ghostfill_refine_schedules[dest_ln]->fillData(0.0,false);
+  }
+}
+
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps/xeqScheduleGhostFillNoCoarse.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps/xeqScheduleGhostFillNoCoarse.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,39 @@
+/*************************************************************************
+ *
+ * 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 Elastic using FAC 
+ *
+ ************************************************************************/
+#include "Elastic/FACOps.h"
+
+void SAMRAI::solv::Elastic::FACOps::xeqScheduleGhostFillNoCoarse(int p_id,
+                                                              int v_id,
+                                                              int dest_ln)
+{
+  /* p */
+  if(p_id!=invalid_id)
+  {
+    if (!p_nocoarse_refine_schedules[dest_ln]) {
+      TBOX_ERROR("Expected cell schedule not found.");
+    }
+    xfer::RefineAlgorithm refiner(d_dim);
+    refiner.registerRefine(p_id,p_id,p_id,tbox::Pointer<xfer::RefineOperator>(0));
+    refiner.resetSchedule(p_nocoarse_refine_schedules[dest_ln]);
+    p_nocoarse_refine_schedules[dest_ln]->fillData(0.0,false);
+  }
+
+  /* v */
+  if(v_id!=invalid_id)
+  {
+    if (!v_nocoarse_refine_schedules[dest_ln]) {
+      TBOX_ERROR("Expected side schedule not found.");
+    }
+    xfer::RefineAlgorithm refiner(d_dim);
+    refiner.registerRefine(v_id,v_id,v_id,tbox::Pointer<xfer::RefineOperator>(0));
+    refiner.resetSchedule(v_nocoarse_refine_schedules[dest_ln]);
+    v_nocoarse_refine_schedules[dest_ln]->fillData(0.0,false);
+  }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps/xeqScheduleProlongation.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps/xeqScheduleProlongation.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,37 @@
+/*************************************************************************
+ *
+ * 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 Elastic using FAC 
+ *
+ ************************************************************************/
+#include "Elastic/FACOps.h"
+
+void SAMRAI::solv::Elastic::FACOps::xeqScheduleProlongation
+(int p_dst, int p_src, int p_scr, int v_dst, int v_src, int v_scr,
+ int dest_ln)
+{
+  /* p */
+  {
+    if (!p_prolongation_refine_schedules[dest_ln]) {
+      TBOX_ERROR("Expected schedule not found.");
+    }
+    xfer::RefineAlgorithm refiner(d_dim);
+    refiner.registerRefine(p_dst, p_src, p_scr, p_prolongation_refine_operator);
+    refiner.resetSchedule(p_prolongation_refine_schedules[dest_ln]);
+    p_prolongation_refine_schedules[dest_ln]->fillData(0.0,false);
+  }
+
+  /* v */
+  {
+    if (!v_prolongation_refine_schedules[dest_ln]) {
+      TBOX_ERROR("Expected schedule not found.");
+    }
+    xfer::RefineAlgorithm refiner(d_dim);
+    refiner.registerRefine(v_dst, v_src, v_scr, v_prolongation_refine_operator);
+    refiner.resetSchedule(v_prolongation_refine_schedules[dest_ln]);
+    v_prolongation_refine_schedules[dest_ln]->fillData(0.0,false);
+  }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps/xeqScheduleRRestriction.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps/xeqScheduleRRestriction.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,39 @@
+/*************************************************************************
+ *
+ * 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 Elastic using FAC 
+ *
+ ************************************************************************/
+#include "Elastic/FACOps.h"
+
+void SAMRAI::solv::Elastic::FACOps::xeqScheduleRRestriction(int p_dst, int p_src,
+                                                         int v_dst, int v_src,
+                                                         int dest_ln)
+{
+  /* p */
+  {
+    if (!p_rrestriction_coarsen_schedules[dest_ln]) {
+      TBOX_ERROR("Expected schedule not found.");
+    }
+
+    xfer::CoarsenAlgorithm coarsener(d_dim);
+    coarsener.registerCoarsen(p_dst,p_src,p_rrestriction_coarsen_operator);
+    coarsener.resetSchedule(p_rrestriction_coarsen_schedules[dest_ln]);
+    p_rrestriction_coarsen_schedules[dest_ln]->coarsenData();
+  }
+
+  /* v */
+  {
+    if (!v_rrestriction_coarsen_schedules[dest_ln]) {
+      TBOX_ERROR("Expected schedule not found.");
+    }
+
+    xfer::CoarsenAlgorithm coarsener(d_dim);
+    coarsener.registerCoarsen(v_dst,v_src,v_rrestriction_coarsen_operator);
+    coarsener.resetSchedule(v_rrestriction_coarsen_schedules[dest_ln]);
+    v_rrestriction_coarsen_schedules[dest_ln]->coarsenData();
+  }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACOps/xeqScheduleURestriction.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACOps/xeqScheduleURestriction.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,39 @@
+/*************************************************************************
+ *
+ * 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 Elastic using FAC 
+ *
+ ************************************************************************/
+#include "Elastic/FACOps.h"
+
+void SAMRAI::solv::Elastic::FACOps::xeqScheduleURestriction(int p_dst, int p_src,
+                                                         int v_dst, int v_src,
+                                                         int dest_ln)
+{
+  /* p */
+  {
+    if (!p_urestriction_coarsen_schedules[dest_ln]) {
+      TBOX_ERROR("Expected schedule not found.");
+    }
+
+    xfer::CoarsenAlgorithm coarsener(d_dim);
+    coarsener.registerCoarsen(p_dst, p_src, p_urestriction_coarsen_operator);
+    coarsener.resetSchedule(p_urestriction_coarsen_schedules[dest_ln]);
+    p_urestriction_coarsen_schedules[dest_ln]->coarsenData();
+  }
+
+  /* v */
+  {
+    if (!v_urestriction_coarsen_schedules[dest_ln]) {
+      TBOX_ERROR("Expected schedule not found.");
+    }
+
+    xfer::CoarsenAlgorithm coarsener(d_dim);
+    coarsener.registerCoarsen(v_dst, v_src, v_urestriction_coarsen_operator);
+    coarsener.resetSchedule(v_urestriction_coarsen_schedules[dest_ln]);
+    v_urestriction_coarsen_schedules[dest_ln]->coarsenData();
+  }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACSolver.I
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACSolver.I	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,117 @@
+/*************************************************************************
+ *
+ * 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 elastic equation. 
+ *
+ ************************************************************************/
+namespace SAMRAI {
+namespace solv {
+
+SAMRAI_INLINE_KEYWORD
+void Elastic::FACSolver::set_P_ProlongationMethod(
+   const std::string& p_prolongation_method)
+{
+   d_fac_ops.set_P_ProlongationMethod(p_prolongation_method);
+}
+
+SAMRAI_INLINE_KEYWORD
+void Elastic::FACSolver::set_V_ProlongationMethod(
+   const std::string& v_prolongation_method)
+{
+   d_fac_ops.set_V_ProlongationMethod(v_prolongation_method);
+}
+
+SAMRAI_INLINE_KEYWORD
+void Elastic::FACSolver::setCoarsestLevelSolverChoice(
+   const std::string& choice)
+{
+   d_fac_ops.setCoarsestLevelSolverChoice(choice);
+}
+
+SAMRAI_INLINE_KEYWORD
+void Elastic::FACSolver::setCoarsestLevelSolverTolerance(
+   double tol)
+{
+   d_fac_ops.setCoarsestLevelSolverTolerance(tol);
+}
+
+SAMRAI_INLINE_KEYWORD
+void Elastic::FACSolver::setCoarsestLevelSolverMaxIterations(
+   int max_iterations)
+{
+   d_fac_ops.setCoarsestLevelSolverMaxIterations(max_iterations);
+}
+
+SAMRAI_INLINE_KEYWORD
+void Elastic::FACSolver::setCoarseFineDiscretization(
+   const std::string& coarsefine_method)
+{
+   d_fac_ops.setCoarseFineDiscretization(coarsefine_method);
+}
+
+#ifdef HAVE_HYPRE
+SAMRAI_INLINE_KEYWORD
+void Elastic::FACSolver::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 Elastic::FACSolver::setPresmoothingSweeps(
+   int num_pre_sweeps) {
+   d_fac_precond.setPresmoothingSweeps(num_pre_sweeps);
+}
+
+SAMRAI_INLINE_KEYWORD
+void Elastic::FACSolver::setPostsmoothingSweeps(
+   int num_post_sweeps) {
+   d_fac_precond.setPostsmoothingSweeps(num_post_sweeps);
+}
+
+SAMRAI_INLINE_KEYWORD
+void Elastic::FACSolver::setMaxCycles(
+   int max_cycles) {
+   d_fac_precond.setMaxCycles(max_cycles);
+}
+
+SAMRAI_INLINE_KEYWORD
+void Elastic::FACSolver::setResidualTolerance(
+   double residual_tol) {
+   d_fac_precond.setResidualTolerance(residual_tol);
+}
+
+SAMRAI_INLINE_KEYWORD
+int Elastic::FACSolver::getNumberOfIterations() const
+{
+   return d_fac_precond.getNumberOfIterations();
+}
+
+SAMRAI_INLINE_KEYWORD
+double Elastic::FACSolver::getResidualNorm() const
+{
+   return d_fac_precond.getResidualNorm();
+}
+
+SAMRAI_INLINE_KEYWORD
+void Elastic::FACSolver::getConvergenceFactors(
+   double& avg_factor,
+   double& final_factor)
+const
+{
+   d_fac_precond.getConvergenceFactors(avg_factor, final_factor);
+}
+
+}
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACSolver.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACSolver.h	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,674 @@
+/*************************************************************************
+ *
+ * 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 Elastic equation. 
+ *
+ ************************************************************************/
+#ifndef GAMRA_ELASTIC_FACSolver_H
+#define GAMRA_ELASTIC_FACSolver_H
+
+#include "SAMRAI/SAMRAI_config.h"
+
+#include "SAMRAI/solv/FACPreconditioner.h"
+#include "Elastic/FACOps.h"
+#include "SAMRAI/solv/SimpleCellRobinBcCoefs.h"
+#include "SAMRAI/tbox/Database.h"
+#include "SAMRAI/tbox/Pointer.h"
+
+namespace SAMRAI {
+namespace solv {
+namespace Elastic {
+/*!
+ * @brief Class for solving scalar Elastic's equation on SAMR grid,
+ * wrapping up lower-level components (FAC cycling, Elastic 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 Elastic::HierarchySolver<DIM> class.
+ * Although this class hides the lower-level components (FAC cycling,
+ * Elastic 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 Elastic
+ * 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 Elastic::FACSolver 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 FACSolver
+{
+
+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)
+    */
+   FACSolver(
+      const tbox::Dimension& dim,
+      const std::string& object_name,
+      tbox::Pointer<tbox::Database> database =
+         tbox::Pointer<tbox::Database>());
+
+   /*!
+    * @brief Destructor.
+    */
+   ~FACSolver(
+      void);
+
+   /*!
+    * @brief Enable logging.
+    *
+    * To disable, pass in @c false.
+    */
+   void
+   enableLogging(
+      bool logging);
+
+   /*!
+    * @brief Solve Elastic'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 p,
+      const int cell_moduli,
+      const int edge_moduli,
+      const int dp,
+      const int p_rhs,
+      const int v,
+      const int v_rhs,
+      tbox::Pointer<hier::PatchHierarchy> hierarchy,
+      int coarse_ln = -1,
+      int fine_ln = -1);
+
+   /*!
+    * @brief Solve Elastic'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 p, const int p_rhs,
+               const int v, const int v_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 Elastic::HYPRESolver 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 "Tackley"
+    * - @c "Gerya"
+    * - @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
+   set_P_ProlongationMethod(
+      const std::string& prolongation_method);
+
+   void
+   set_V_ProlongationMethod(
+      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 p,
+                         const int cell_moduli,
+                         const int edge_moduli,
+                         const int dp,
+                         const int p_rhs,
+                         const int v,
+                         const int v_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;
+
+  void set_boundaries(const int &p_id, const int &v_id,
+                      tbox::Pointer<hier::PatchLevel> &level,
+                      const bool &homogeneous)
+  {
+    d_fac_ops.set_boundaries(p_id,v_id,level,homogeneous);
+  }
+
+
+   //@}
+
+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 p, int p_rhs, int v, int v_rhs);
+
+   /*
+    * @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 FAC operator implementation corresponding to cell-centered
+    * Elastic discretization.
+    */
+  FACOps 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 "Elastic/FACSolver.I"
+#endif
+
+#endif  // included_solv_ElasticFACSolver
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACSolver/FACSolver.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACSolver/FACSolver.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,158 @@
+/*************************************************************************
+ *
+ * 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 elastic equation. 
+ *
+ ************************************************************************/
+#include "SAMRAI/pdat/CellVariable.h"
+#include "Elastic/FACSolver.h"
+#include "SAMRAI/tbox/PIO.h"
+#include "SAMRAI/tbox/Utilities.h"
+#include "SAMRAI/tbox/StartupShutdownManager.h"
+
+#include IOMANIP_HEADER_FILE
+
+#ifndef SAMRAI_INLINE
+#include "Elastic/FACSolver.I"
+#endif
+
+namespace SAMRAI {
+  namespace solv {
+
+    /*
+*************************************************************************
+*                                                                       *
+* Initialize the static data members.                                   *
+*                                                                       *
+*************************************************************************
+*/
+
+    bool Elastic::FACSolver::s_initialized = 0;
+    int Elastic::FACSolver::s_weight_id[SAMRAI::tbox::Dimension::
+                                        MAXIMUM_DIMENSION_VALUE];
+    int Elastic::FACSolver::s_instance_counter[SAMRAI::tbox::Dimension::
+                                               MAXIMUM_DIMENSION_VALUE];
+
+    /*
+*************************************************************************
+*                                                                       *
+* Constructor sets uninitialized solver state.                          *
+* Set default iteration and convergence parameters.                     *
+*                                                                       *
+* By default settings:                                                  *
+*   - Elastic equation specified has D=1, C=0.                          *
+*   - State is uninitialized                                            *
+*   - Logging is disabled                                               *
+*   - Context for internal data is set based on object name.            *
+*                                                                       *
+*************************************************************************
+*/
+
+    Elastic::FACSolver::FACSolver(const tbox::Dimension& dim,
+                                  const std::string& object_name,
+                                  tbox::Pointer<tbox::Database> database):
+      d_dim(dim),
+      d_object_name(object_name),
+      d_fac_ops(d_dim, object_name + "::fac_ops",database),
+      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("Tackley");
+      setCoarsestLevelSolverTolerance(1e-8);
+      setCoarsestLevelSolverMaxIterations(10);
+// #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 cell_weight_name("Elastic::FACSolver_cell_weight");
+
+        tbox::Pointer<pdat::CellVariable<double> >
+          weight = var_db->getVariable(cell_weight_name);
+        if (weight.isNull()) {
+          weight = new pdat::CellVariable<double>(d_dim, cell_weight_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));
+        }
+      }
+
+      {
+        static std::string side_weight_name("Elastic::FACSolver_side_weight");
+
+        tbox::Pointer<pdat::SideVariable<double> >
+          weight = var_db->getVariable(side_weight_name);
+        if (weight.isNull()) {
+          weight = new pdat::SideVariable<double>(d_dim, side_weight_name, 1);
+        }
+
+        if (s_weight_id[d_dim.getValue() - 2] < 0) {
+          s_weight_id[d_dim.getValue() - 2] =
+            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]++;
+    }
+
+  }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACSolver/FACSolver_Destructor.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACSolver/FACSolver_Destructor.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,41 @@
+/*************************************************************************
+ *
+ * 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 Elastic equation. 
+ *
+ ************************************************************************/
+
+#include "SAMRAI/pdat/CellVariable.h"
+#include "Elastic/FACSolver.h"
+#include "SAMRAI/tbox/PIO.h"
+#include "SAMRAI/tbox/Utilities.h"
+#include "SAMRAI/tbox/StartupShutdownManager.h"
+
+#include IOMANIP_HEADER_FILE
+
+namespace SAMRAI {
+  namespace solv {
+    /*
+*************************************************************************
+*                                                                       *
+* Destructor for Elastic::FACSolver.                            *
+* Deallocate internal data.                                             *
+*                                                                       *
+*************************************************************************
+*/
+    Elastic::FACSolver::~FACSolver()
+    {
+      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;
+      }
+    }
+
+  }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACSolver/createVectorWrappers.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACSolver/createVectorWrappers.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,97 @@
+/*************************************************************************
+ *
+ * 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 Elastic equation. 
+ *
+ ************************************************************************/
+#include "SAMRAI/pdat/CellVariable.h"
+#include "Elastic/FACSolver.h"
+#include "SAMRAI/tbox/PIO.h"
+#include "SAMRAI/tbox/Utilities.h"
+#include "SAMRAI/tbox/StartupShutdownManager.h"
+
+#include IOMANIP_HEADER_FILE
+
+void SAMRAI::solv::Elastic::FACSolver::createVectorWrappers(int p, int p_rhs,
+                                                         int v, int v_rhs) {
+
+  hier::VariableDatabase& vdb(*hier::VariableDatabase::getDatabase());
+  tbox::Pointer<hier::Variable> variable;
+
+  if (!d_uv || d_uv->getComponentDescriptorIndex(0) != p) {
+    d_uv.setNull();
+    d_uv = new SAMRAIVectorReal<double>(d_object_name + "::uv",
+                                        d_hierarchy,
+                                        d_ln_min,
+                                        d_ln_max);
+    /* Add p */
+    vdb.mapIndexToVariable(p, variable);
+#ifdef DEBUG_CHECK_ASSERTIONS
+    if (!variable) {
+      TBOX_ERROR(d_object_name << ": No variable for patch data index "
+                 << p << "\n");
+    }
+    tbox::Pointer<pdat::CellVariable<double> > cell_variable = variable;
+    if (!cell_variable) {
+      TBOX_ERROR(d_object_name << ": hier::Patch data index " << p
+                 << " is not a cell-double variable.\n");
+    }
+#endif
+    d_uv->addComponent(variable, p, s_weight_id[d_dim.getValue() - 1]);
+
+    /* Add v */
+    vdb.mapIndexToVariable(v, variable);
+#ifdef DEBUG_CHECK_ASSERTIONS
+    if (!variable) {
+      TBOX_ERROR(d_object_name << ": No variable for patch data index "
+                 << v << "\n");
+    }
+    tbox::Pointer<pdat::SideVariable<double> > side_variable = variable;
+    if (!side_variable) {
+      TBOX_ERROR(d_object_name << ": hier::Patch data index " << v
+                 << " is not a side-double variable.\n");
+    }
+#endif
+    d_uv->addComponent(variable, v);
+  }
+
+  if (!d_fv || d_fv->getComponentDescriptorIndex(0) != p_rhs) {
+    d_fv.setNull();
+    d_fv = new SAMRAIVectorReal<double>(d_object_name + "::fv",
+                                        d_hierarchy,
+                                        d_ln_min,
+                                        d_ln_max);
+    /* Add p_rhs */
+    vdb.mapIndexToVariable(p_rhs, variable);
+#ifdef DEBUG_CHECK_ASSERTIONS
+    if (!variable) {
+      TBOX_ERROR(d_object_name << ": No variable for patch data index "
+                 << p_rhs << "\n");
+    }
+    tbox::Pointer<pdat::CellVariable<double> > cell_variable = variable;
+    if (!cell_variable) {
+      TBOX_ERROR(d_object_name << ": hier::Patch data index " << p_rhs
+                 << " is not a cell-double variable.\n");
+    }
+#endif
+    d_fv->addComponent(variable, p_rhs, s_weight_id[d_dim.getValue() - 1]);
+
+    /* Add v_rhs */
+    vdb.mapIndexToVariable(v_rhs, variable);    
+#ifdef DEBUG_CHECK_ASSERTIONS
+    if (!variable) {
+      TBOX_ERROR(d_object_name << ": No variable for patch data index "
+                 << v_rhs << "\n");
+    }
+    tbox::Pointer<pdat::SideVariable<double> > side_variable = variable;
+    if (!side_variable) {
+      TBOX_ERROR(d_object_name << ": hier::Patch data index " << v_rhs
+                 << " is not a cell-double variable.\n");
+    }
+#endif
+    d_fv->addComponent(variable, v_rhs);
+  }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACSolver/deallocateSolverState.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACSolver/deallocateSolverState.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,47 @@
+/*************************************************************************
+ *
+ * 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 Elastic equation. 
+ *
+ ************************************************************************/
+#include "SAMRAI/pdat/CellVariable.h"
+#include "Elastic/FACSolver.h"
+#include "SAMRAI/tbox/PIO.h"
+#include "SAMRAI/tbox/Utilities.h"
+#include "SAMRAI/tbox/StartupShutdownManager.h"
+
+#include IOMANIP_HEADER_FILE
+
+namespace SAMRAI {
+  namespace solv {
+
+    void Elastic::FACSolver::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();
+
+      }
+    }
+
+  }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACSolver/destroyVectorWrappers.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACSolver/destroyVectorWrappers.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,33 @@
+/*************************************************************************
+ *
+ * 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 Elastic equation. 
+ *
+ ************************************************************************/
+#include "SAMRAI/pdat/CellVariable.h"
+#include "Elastic/FACSolver.h"
+#include "SAMRAI/tbox/PIO.h"
+#include "SAMRAI/tbox/Utilities.h"
+#include "SAMRAI/tbox/StartupShutdownManager.h"
+
+#include IOMANIP_HEADER_FILE
+
+namespace SAMRAI {
+  namespace solv {
+
+    /*
+***********************************************************************
+* Delete the vector wrappers.  Do not freeVectorComponents because    *
+* we do not control their data allocation.  The user does that.       *
+***********************************************************************
+*/
+    void Elastic::FACSolver::destroyVectorWrappers() {
+      d_uv.setNull();
+      d_fv.setNull();
+    }
+
+  }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACSolver/enableLogging.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACSolver/enableLogging.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,37 @@
+/*************************************************************************
+ *
+ * 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 Elastic equation. 
+ *
+ ************************************************************************/
+#include "SAMRAI/pdat/CellVariable.h"
+#include "Elastic/FACSolver.h"
+#include "SAMRAI/tbox/PIO.h"
+#include "SAMRAI/tbox/Utilities.h"
+#include "SAMRAI/tbox/StartupShutdownManager.h"
+
+#include IOMANIP_HEADER_FILE
+
+namespace SAMRAI {
+  namespace solv {
+
+
+    /*
+*************************************************************************
+* Enable logging and propagate logging flag to major components.        *
+*************************************************************************
+*/
+
+    void Elastic::FACSolver::enableLogging(
+                                        bool logging)
+    {
+      d_enable_logging = logging;
+      d_fac_precond.enableLogging(d_enable_logging);
+      d_fac_ops.enableLogging(d_enable_logging);
+    }
+
+  }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACSolver/getFromInput.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACSolver/getFromInput.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,96 @@
+/*************************************************************************
+ *
+ * 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 Elastic equation. 
+ *
+ ************************************************************************/
+
+#include "SAMRAI/pdat/CellVariable.h"
+#include "Elastic/FACSolver.h"
+#include "SAMRAI/tbox/PIO.h"
+#include "SAMRAI/tbox/Utilities.h"
+#include "SAMRAI/tbox/StartupShutdownManager.h"
+
+#include IOMANIP_HEADER_FILE
+
+namespace SAMRAI {
+  namespace solv {
+
+
+    /*
+********************************************************************
+* Set state from database                                          *
+*                                                                  *
+* Do not allow FAC preconditioner and Elastic 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 Elastic::FACSolver::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("p_prolongation_method")) {
+          std::string s = database->getString("p_prolongation_method");
+          set_P_ProlongationMethod(s);
+        }
+        if (database->isString("v_prolongation_method")) {
+          std::string s = database->getString("v_prolongation_method");
+          set_V_ProlongationMethod(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
+      }
+    }
+
+
+  }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACSolver/initializeSolverState.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACSolver/initializeSolverState.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,107 @@
+/*************************************************************************
+ *
+ * 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 Elastic equation. 
+ *
+ ************************************************************************/
+#include "SAMRAI/pdat/CellVariable.h"
+#include "Elastic/FACSolver.h"
+#include "SAMRAI/tbox/PIO.h"
+#include "SAMRAI/tbox/Utilities.h"
+#include "SAMRAI/tbox/StartupShutdownManager.h"
+
+#include IOMANIP_HEADER_FILE
+
+/*
+*************************************************************************
+*                                                                       *
+* 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                  *
+* Elastic FAC operator.                                                 *
+*                                                                       *
+*************************************************************************
+*/
+
+void SAMRAI::solv::Elastic::FACSolver::initializeSolverState
+(const int p,
+ const int cell_moduli,
+ const int edge_moduli,
+ const int dp,
+ const int p_rhs,
+ const int v,
+ const int v_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 (p < 0 || p_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);
+  }
+
+  d_fac_ops.set_moduli_id(cell_moduli,edge_moduli);
+
+  createVectorWrappers(p, p_rhs, v, v_rhs);
+
+  d_fac_precond.initializeSolverState(*d_uv, *d_fv);
+
+  d_solver_is_initialized = true;
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACSolver/initializeStatics.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACSolver/initializeStatics.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,32 @@
+/*************************************************************************
+ *
+ * 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 Elastic equation. 
+ *
+ ************************************************************************/
+#include "SAMRAI/pdat/CellVariable.h"
+#include "Elastic/FACSolver.h"
+#include "SAMRAI/tbox/PIO.h"
+#include "SAMRAI/tbox/Utilities.h"
+#include "SAMRAI/tbox/StartupShutdownManager.h"
+
+#include IOMANIP_HEADER_FILE
+
+namespace SAMRAI {
+  namespace solv {
+
+    void Elastic::FACSolver::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;
+    }
+
+  }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACSolver/setBcObject.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACSolver/setBcObject.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,36 @@
+/*************************************************************************
+ *
+ * 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 Elastic equation. 
+ *
+ ************************************************************************/
+#include "SAMRAI/pdat/CellVariable.h"
+#include "Elastic/FACSolver.h"
+#include "SAMRAI/tbox/PIO.h"
+#include "SAMRAI/tbox/Utilities.h"
+#include "SAMRAI/tbox/StartupShutdownManager.h"
+
+#include IOMANIP_HEADER_FILE
+
+namespace SAMRAI {
+  namespace solv {
+
+
+    void Elastic::FACSolver::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);
+    }
+
+  }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACSolver/setBoundaries.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACSolver/setBoundaries.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,45 @@
+/*************************************************************************
+ *
+ * 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 Elastic equation. 
+ *
+ ************************************************************************/
+#include "SAMRAI/pdat/CellVariable.h"
+#include "Elastic/FACSolver.h"
+#include "SAMRAI/tbox/PIO.h"
+#include "SAMRAI/tbox/Utilities.h"
+#include "SAMRAI/tbox/StartupShutdownManager.h"
+
+#include IOMANIP_HEADER_FILE
+
+namespace SAMRAI {
+  namespace solv {
+
+    void Elastic::FACSolver::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);
+    }
+
+
+  }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/FACSolver/solveSystem.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/FACSolver/solveSystem.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,128 @@
+/*************************************************************************
+ *
+ * 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 Elastic equation. 
+ *
+ ************************************************************************/
+#include "SAMRAI/pdat/CellVariable.h"
+#include "Elastic/FACSolver.h"
+#include "SAMRAI/tbox/PIO.h"
+#include "SAMRAI/tbox/Utilities.h"
+#include "SAMRAI/tbox/StartupShutdownManager.h"
+
+#include IOMANIP_HEADER_FILE
+
+/*
+*************************************************************************
+*                                                                       *
+* 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 SAMRAI::solv::Elastic::FACSolver::solveSystem(const int p,
+                                                const int p_rhs,
+                                                const int v, const int v_rhs)
+{
+#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 (p < 0 || p_rhs < 0 || v < 0 || v_rhs < 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(p);
+  }
+
+  createVectorWrappers(p, p_rhs, v, v_rhs);
+  bool solver_rval;
+
+  solver_rval = d_fac_precond.solveSystem(*d_uv, *d_fv);
+
+  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 SAMRAI::solv::Elastic::FACSolver::solveSystem
+(const int p,
+ const int cell_moduli,
+ const int edge_moduli,
+ const int dp,
+ const int p_rhs,
+ const int v,
+ const int v_rhs,
+ 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 << "Elastic::FACSolver::solveSystem (" << d_object_name
+               << ")\n";
+  }
+#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(p, cell_moduli, edge_moduli, dp, p_rhs, v, v_rhs,
+                        hierarchy, coarse_ln, fine_ln);
+
+  bool solver_rval;
+  solver_rval = solveSystem(p, p_rhs, v, v_rhs);
+
+  deallocateSolverState();
+
+  return solver_rval;
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/HypreSolver.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/HypreSolver.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,1545 @@
+/*************************************************************************
+ *
+ * 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. 
+ *
+ ************************************************************************/
+#include "Elastic/HypreSolver.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 "Elastic/HypreSolver.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> >
+Elastic::HypreSolver::s_Ak0_var[tbox::Dimension::MAXIMUM_DIMENSION_VALUE];
+
+  tbox::StartupShutdownManager::Handler Elastic::HypreSolver::s_finalize_handler(
+   0,
+   0,
+   0,
+   Elastic::HypreSolver::finalizeCallback,
+   tbox::StartupShutdownManager::priorityVariables);
+
+/*
+ *************************************************************************
+ * Constructor                                                           *
+ *************************************************************************
+ */
+
+  Elastic::HypreSolver::HypreSolver(
+   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(" Elastic::HypreSolver : DIM == 1 or > 3 not implemented");
+   }
+
+   t_solve_system = tbox::TimerManager::getManager()->
+      getTimer("solv::Elastic::HypreSolver::solveSystem()");
+   t_set_matrix_coefficients = tbox::TimerManager::getManager()->
+      getTimer("solv::Elastic::HypreSolver::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 Elastic::HypreSolver::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("Elastic::HypreSolver 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 Elastic::HypreSolver::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 Elastic::HypreSolver::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 Elastic::HypreSolver::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(
+            "Elastic::HypreSolver 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.                               *
+ *                                                                       *
+ *************************************************************************
+ */
+
+  Elastic::HypreSolver::~HypreSolver()
+{
+   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 Elastic::HypreSolver::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 Elastic::HypreSolver::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 Elastic::HypreSolver::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 Elastic::Specificiations            *
+ * object and by the boundary condition.                                 *
+ *                                                                       *
+ *************************************************************************
+ */
+
+  void Elastic::HypreSolver::setMatrixCoefficients()
+{
+   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();
+
+      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.
+       */
+      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.
+       */
+      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 "
+                  <<
+                  "Elastic::HypreSolver::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 "
+                  <<
+                  "Elastic::HypreSolver::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 Elastic::HypreSolver::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 "
+                                  << "Elastic::HypreSolver::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 Elastic::HypreSolver::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 Elastic::HypreSolver::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 Elastic::HypreSolver::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("Elastic::HypreSolver::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 Elastic::HypreSolver::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 Elastic::HypreSolver::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("Elastic::HypreSolver error...\n"
+         << "DIM > 3 not supported." << std::endl);
+   }
+}
+
+void Elastic::HypreSolver::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("Elastic::HypreSolver error...\n"
+         << "DIM > 3 not supported." << std::endl);
+   }
+}
+
+void Elastic::HypreSolver::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("Elastic::HypreSolver error...\n"
+         << "DIM > 3 not supported." << std::endl);
+   }
+}
+
+void
+Elastic::HypreSolver::finalizeCallback()
+{
+   for (int d = 0; d < tbox::Dimension::MAXIMUM_DIMENSION_VALUE; ++d) {
+      s_Ak0_var[d].setNull();
+   }
+}
+
+}
+}
+
+#endif
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/HypreSolver.I
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/HypreSolver.I	Thu Jun 07 13:34:24 2012 -0700
@@ -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 Elastic::HypreSolver::setSolnIdDepth(
+   const int depth) {
+   d_soln_depth = depth;
+}
+
+SAMRAI_INLINE_KEYWORD
+void Elastic::HypreSolver::setRhsIdDepth(
+   const int depth) {
+   d_rhs_depth = depth;
+}
+
+SAMRAI_INLINE_KEYWORD
+void Elastic::HypreSolver::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 Elastic::HypreSolver::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 Elastic::HypreSolver::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 Elastic::HypreSolver::getNumberOfIterations() const
+{
+   return d_number_iterations;
+}
+
+SAMRAI_INLINE_KEYWORD
+double Elastic::HypreSolver::getRelativeResidualNorm() const
+{
+   return d_relative_residual_norm;
+}
+
+SAMRAI_INLINE_KEYWORD
+void Elastic::HypreSolver::setNumPreRelaxSteps(
+   const int steps)
+{
+#ifdef DEBUG_CHECK_ASSERTIONS
+   TBOX_ASSERT(!d_hierarchy.isNull());
+#endif
+   d_num_pre_relax_steps = steps;
+}
+
+SAMRAI_INLINE_KEYWORD
+void Elastic::HypreSolver::setNumPostRelaxSteps(
+   const int steps)
+{
+#ifdef DEBUG_CHECK_ASSERTIONS
+   TBOX_ASSERT(!d_hierarchy.isNull());
+#endif
+   d_num_post_relax_steps = steps;
+}
+
+SAMRAI_INLINE_KEYWORD
+void Elastic::HypreSolver::setPrintSolverInfo(
+   const bool print)
+{
+   d_print_solver_info = print;
+}
+
+SAMRAI_INLINE_KEYWORD
+void Elastic::HypreSolver::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 2816cd6f8030 -r c77b196abc8c src/Elastic/HypreSolver.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/HypreSolver.h	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,616 @@
+/*************************************************************************
+ *
+ * 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 GAMRA_ELASTIC_HypreSolver_H
+#define GAMRA_ELASTIC_HypreSolver_H
+
+#include "SAMRAI/SAMRAI_config.h"
+
+#ifdef HAVE_HYPRE
+
+#ifndef GAMRA_ELASTIC_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 GAMRA_ELASTIC_HYPRE_STRUCT_LS
+#endif
+
+#include "SAMRAI/solv/GhostCellRobinBcCoefs.h"
+#include "SAMRAI/solv/RobinBcCoefStrategy.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 {
+namespace Elastic {
+/*!
+ * @brief Use the HYPRE preconditioner library to solve (the cell-centered)
+ * Elastic's equation on a single level in a hierarchy.
+ *
+ * Class Elastic::HypreSolver 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 Elastic::Specifications).
+ * 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
+ * Elastic::HypreSolver:
+ * - Create a Elastic::HypreSolver object.
+ * - Initialize Elastic::HypreSolver 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 HypreSolver
+{
+public:
+   /*!
+    * @brief Constructor.
+    *
+    * @param object_name Name of object.
+    * @param database tbox::Database for input.
+    */
+   HypreSolver(
+      const tbox::Dimension& dim,
+      const std::string& object_name,
+      tbox::Pointer<tbox::Database> database =
+         tbox::Pointer<tbox::Database>(NULL));
+
+   /*!
+    * The Elastic destructor releases all internally managed data.
+    */
+   ~HypreSolver();
+
+   /*!
+    * @brief Initialize to a given hierarchy.
+    *
+    * Initializer Elastic 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 Elastic equation parameters,
+    * see the light-weight Elastic::Specifications class where
+    * you set the values of C and D.
+    *
+    * This method must be called before solveSystem().
+    */
+   void
+   setMatrixCoefficients();
+
+   /*!
+    * @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 "Elastic/HypreSolver.I"
+#endif
+
+#endif
+
+#endif
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/P_Boundary_Refine.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/P_Boundary_Refine.h	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,140 @@
+/*************************************************************************
+ *
+ * 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:   Linear refine operator for cell-centered double data on
+ *                a Cartesian mesh. 
+ *
+ ************************************************************************/
+
+#ifndef GAMRA_ELASTIC_P_BOUNDARY_REFINE_H
+#define GAMRA_ELASTIC_P_BOUNDARY_REFINE_H
+
+#include "SAMRAI/SAMRAI_config.h"
+
+#include "SAMRAI/xfer/RefineOperator.h"
+#include "SAMRAI/hier/Box.h"
+#include "SAMRAI/hier/IntVector.h"
+#include "SAMRAI/hier/Patch.h"
+#include "SAMRAI/tbox/Pointer.h"
+#include "SAMRAI/pdat/CellVariable.h"
+#include "SAMRAI/geom/CartesianPatchGeometry.h"
+
+#include <string>
+
+namespace SAMRAI {
+namespace geom {
+namespace Elastic {
+
+/**
+ * Class P_Boundary_Refine implements the special interpolation needed
+ * for the boundary elements on the coarse-fine interface.
+ *
+ * The findRefineOperator() operator function returns true if the input
+ * variable is cell-centered double, and the std::string is "P_BOUNDARY_REFINE".
+ *
+ * @see xfer::RefineOperator
+ */
+
+class P_Boundary_Refine:
+  public xfer::RefineOperator
+{
+public:
+  /**
+   * Uninteresting default constructor.
+   */
+  explicit P_Boundary_Refine(const tbox::Dimension& dim):
+    xfer::RefineOperator(dim, "P_BOUNDARY_REFINE")
+  {
+    d_name_id = "P_BOUNDARY_REFINE";
+  }
+
+
+  /**
+   * Uninteresting virtual destructor.
+   */
+  virtual ~P_Boundary_Refine(){}
+
+  /**
+   * Return true if the variable and name std::string match cell-centered
+   * double linear interpolation; otherwise, return false.
+   */
+  bool findRefineOperator(const tbox::Pointer<hier::Variable>& var,
+                          const std::string& op_name) const
+  {
+    TBOX_DIM_ASSERT_CHECK_ARGS2(*this, *var);
+
+    const tbox::Pointer<pdat::CellVariable<double> > cast_var(var);
+    if (!cast_var.isNull() && (op_name == d_name_id)) {
+      return true;
+    } else {
+      return false;
+    }
+  }
+  /**
+   * Return name std::string identifier of this refinement operator.
+   */
+  const std::string& getOperatorName() const
+  {
+    return d_name_id;
+  }
+
+  /**
+   * The priority of cell-centered double linear interpolation is 0.
+   * It will be performed before any user-defined interpolation operations.
+   */
+  int getOperatorPriority() const
+  {
+    return 0;
+  }
+
+  /**
+   * The stencil width of the linear interpolation operator is the vector
+   * of ones.  That is, its stencil extends one cell outside the fine box.
+   */
+  hier::IntVector getStencilWidth() const
+  {
+    return hier::IntVector::getOne(getDim());
+  }
+
+  /**
+   * Refine the source component on the coarse patch to the destination
+   * component on the fine patch using the cell-centered double linear
+   * interpolation operator.  Interpolation is performed on the intersection
+   * of the destination patch and the boxes contained in fine_overlap
+   * It is assumed that the coarse patch contains sufficient data for the
+   * stencil width of the refinement operator.
+   */
+  virtual void refine(hier::Patch& fine,
+                      const hier::Patch& coarse,
+                      const int dst_component,
+                      const int src_component,
+                      const hier::BoxOverlap& fine_overlap,
+                      const hier::IntVector& ratio) const;
+
+
+private:
+  std::string d_name_id;
+
+  void Update_P_2D(const pdat::CellIndex &fine,
+                   const hier::Index &ip, const hier::Index &jp,
+                   const int &j, const int &j_max,
+                   SAMRAI::pdat::CellData<double> &p,
+                   SAMRAI::pdat::CellData<double> &p_fine)
+    const;
+
+  void Update_P_3D(const pdat::CellIndex &fine,
+                   const hier::Index &ip, const hier::Index &jp,
+                   const hier::Index &kp,
+                   const int &j, const int &k, const int &j_max, const int &k_max,
+                   SAMRAI::pdat::CellData<double> &p,
+                   SAMRAI::pdat::CellData<double> &p_fine)
+    const;
+};
+
+}
+}
+}
+#endif
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/P_Boundary_Refine/Update_P_2D.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/P_Boundary_Refine/Update_P_2D.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,74 @@
+#include "Elastic/P_Boundary_Refine.h"
+
+/* Interpolate the pressure from the coarse (C) to the fine (f+/-)
+   coordinates using the intermediate fine points (F+/-, F_).
+
+         i-1      i       i+1
+
+        ------- -------
+       |       |       |
+   j-1 |   C   |   C   |   C
+       |       |       |
+        ------- -------
+       |       |f- F-  |
+   j   |   C   |F_ C   |   C
+       |       |f+ F+  |
+        ------- -------
+       |       |       |
+   j+1 |   C   |   C   |   C
+       |       |       |
+        ------- -------
+
+   C= a + b*x + c*x^2 + d*y + e*y^2 + f*x*y
+
+   C(0,0)=a
+   C(+,0)=a+b+c
+   C(-,0)=a-b+c
+   C(0,+)=a+d+e
+   C(0,-)=a-d+e
+   C(-,-)=a-b+c-d+e+f
+
+   f(-,-) = a - b/4 + c/16 - d/4 + e/16 + f/16
+          = C(-,-)/16 + (15/16)*C(0,0)
+            + (3/32)*(-C(+,0) - C(0,+) + C(-,0) + C(0,-))
+   
+   This example show a boundary in the positive x direction.  To reverse
+   the direction, pass in ip -> -ip.  To do the y direction, switch ip
+   and jp, and replace j with i.
+
+*/
+     
+
+void SAMRAI::geom::Elastic::P_Boundary_Refine::Update_P_2D
+(const pdat::CellIndex &fine,
+ const hier::Index &ip, const hier::Index &jp,
+ const int &j, const int &j_max,
+ SAMRAI::pdat::CellData<double> &p,
+ SAMRAI::pdat::CellData<double> &p_fine) const
+{
+  pdat::CellIndex center(fine);
+  center.coarsen(hier::Index(2,2));
+
+    
+  /* If we are at an even index, update both of the elements in the cell */
+  if(j%2==0)
+    {
+      const double p_low=p(center-ip-jp)/16 + (15.0/16)*p(center)
+        + (3.0/32)*(-p(center+ip) - p(center+jp) + p(center-ip) + p(center-jp));
+      p_fine(fine)=p_low;
+      if(j<j_max)
+        {
+          const double p_high=p(center-ip+jp)/16 + (15.0/16)*p(center)
+            + (3.0/32)*(-p(center+ip) - p(center-jp)
+                        + p(center-ip) + p(center+jp));
+          p_fine(fine+jp)=p_high;
+        }
+    }
+  else
+    {
+      const double p_high=p(center-ip+jp)/16 + (15.0/16)*p(center)
+        + (3.0/32)*(-p(center+ip) - p(center-jp)
+                    + p(center-ip) + p(center+jp));
+      p_fine(fine)=p_high;
+    }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/P_Boundary_Refine/Update_P_3D.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/P_Boundary_Refine/Update_P_3D.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,113 @@
+#include "Elastic/P_Boundary_Refine.h"
+
+/* Interpolate the pressure from the coarse (C) to the fine (f+/-)
+   coordinates using the intermediate fine points (F+/-, F_).
+
+          i-1      i       i+1
+
+        ------- -------
+       |       |       |
+   j-1 |  C    |   C   |   C
+       |       |       |
+       ------- -------
+       |       |f- Y-  |
+   j   |   C   |X_ C   |   C
+       |       |f+ Y+  |
+       ------- -------
+       |       |       |
+   j+1 |   C   |   C   |   C
+       |       |       |
+       ------- -------
+
+
+   C= a + b*x + c*x^2 + d*y + e*y^2 + f*z + g*z^2
+        + h*x*y + i*x*z + j*y*z + k*x*y*z
+
+   C(0,0,0)=a
+   C(+,0,0)=a+b+c
+   C(-,0,0)=a-b+c
+   C(0,+,0)=a+d+e
+   C(0,-,0)=a-d+e
+   C(-,-,0)=a-b+c-d+e+h
+   C(-,-,-)=a-b+c-d+e-f+g+h+i+j-k
+
+   f(-,-) = a - b/4 + c/16 - d/4 + e/16 - f/4 + g/16 + h/16 + i/16 + j/16 - k/64
+          = C(-,-)/64 + (63/64)*C(0,0)
+            - (6/64)*(C(+,0,0) + C(0,+,0) + C(0,0,+))
+            + (3/64)*(C(-,0,0) + C(0,-,0) + C(0,0,-)
+                      + C(-,-,0) + C(-,0,-) + C(0,-,-))
+
+   Note that if, for example, C is constant in the Z direction, then
+   this formula reduces to the one used in Update_P_2D.
+
+   This example show a boundary in the positive x direction.  To
+   reverse the direction, pass in ip -> -ip.  To do the y direction,
+   rotate [ip,jp,kp], and switch j with k.  To do z, rotate again and
+   switch k with i.
+*/
+     
+
+void SAMRAI::geom::Elastic::P_Boundary_Refine::Update_P_3D
+(const pdat::CellIndex &fine,
+ const hier::Index &ip, const hier::Index &jp, const hier::Index &kp,
+ const int &j, const int &k, const int &j_max, const int &k_max,
+ SAMRAI::pdat::CellData<double> &p,
+ SAMRAI::pdat::CellData<double> &p_fine) const
+{
+  pdat::CellIndex center(fine);
+  center.coarsen(hier::Index(2,2,2));
+
+  const double p_mmm=p(center-ip-jp-kp)/64 + (63.0/64)*p(center)
+    - (3.0/32) * (p(center+ip) + p(center+jp) + p(center+kp))
+    + (3.0/64) * (p(center-ip) + p(center-jp) + p(center-kp)
+                  + p(center-ip-jp) + p(center-jp-kp) + p(center-ip-kp));
+
+  const double p_mmp=p(center-ip-jp+kp)/64 + (63.0/64)*p(center)
+    - (3.0/32) * (p(center+ip) + p(center+jp) + p(center-kp))
+    + (3.0/64) * (p(center-ip) + p(center-jp) + p(center+kp)
+                  + p(center-ip-jp) + p(center-jp+kp) + p(center-ip+kp));
+
+  const double p_mpm=p(center-ip+jp-kp)/64 + (63.0/64)*p(center)
+    - (3.0/32) * (p(center+ip) + p(center-jp) + p(center+kp))
+    + (3.0/64) * (p(center-ip) + p(center+jp) + p(center-kp)
+                  + p(center-ip+jp) + p(center+jp-kp) + p(center-ip-kp));
+
+  const double p_mpp=p(center-ip+jp+kp)/64 + (63.0/64)*p(center)
+    - (3.0/32) * (p(center+ip) + p(center-jp) + p(center-kp))
+    + (3.0/64) * (p(center-ip) + p(center+jp) + p(center+kp)
+                  + p(center-ip+jp) + p(center+jp+kp) + p(center-ip+kp));
+
+  /* If we are at an even index, update both of the elements in the cell */
+  if(j%2==0)
+    {
+      if(k%2==0)
+        {
+          p_fine(fine)=p_mmm;
+          if(j<j_max)
+            p_fine(fine+jp)=p_mpm;
+          if(k<k_max)
+            p_fine(fine+kp)=p_mmp;
+          if(j<j_max && k<k_max)
+            p_fine(fine+jp+kp)=p_mpp;
+        }
+      else
+        {
+          p_fine(fine)=p_mmp;
+          if(j<j_max)
+            p_fine(fine+jp)=p_mpp;
+        }
+    }
+  else
+    {
+      if(k%2==0)
+        {
+          p_fine(fine)=p_mpm;
+          if(k<k_max)
+            p_fine(fine+kp)=p_mpp;
+        }
+      else
+        {
+          p_fine(fine)=p_mpp;
+        }
+    }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/P_Boundary_Refine/refine.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/P_Boundary_Refine/refine.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,125 @@
+#include "Elastic/P_Boundary_Refine.h"
+#include "Elastic/set_boundary.h"
+#include "Constants.h"
+
+void SAMRAI::geom::Elastic::P_Boundary_Refine::refine
+(hier::Patch& fine,
+ const hier::Patch& coarse,
+ const int dst_component,
+ const int src_component,
+ const hier::BoxOverlap& overlap,
+ const hier::IntVector& ratio) const
+{
+  const pdat::CellOverlap* t_overlap =
+    dynamic_cast<const pdat::CellOverlap *>(&overlap);
+  const hier::BoxList& boxes = t_overlap->getDestinationBoxList();
+  const tbox::Dimension& dimension(getDim());
+  const int dim(dimension.getValue());
+
+  set_boundary(coarse,src_component,invalid_id,true);
+
+  for (hier::BoxList::Iterator b(boxes); b; b++)
+    {
+      hier::Box &overlap_box=b();
+      TBOX_DIM_ASSERT_CHECK_DIM_ARGS4(dimension,fine,coarse,overlap_box,ratio);
+
+      tbox::Pointer<pdat::CellData<double> >
+        p = coarse.getPatchData(src_component);
+      tbox::Pointer<pdat::CellData<double> >
+        p_fine = fine.getPatchData(dst_component);
+#ifdef DEBUG_CHECK_ASSERTIONS
+      TBOX_ASSERT(!p.isNull());
+      TBOX_ASSERT(!p_fine.isNull());
+      TBOX_ASSERT(p->getDepth() == p_fine->getDepth());
+      TBOX_ASSERT(p->getDepth() == 1);
+#endif
+
+      hier::Box fine_box=fine.getBox();
+      hier::Box gbox=p_fine->getGhostBox();
+
+      /* We have to infer where the boundary is from the boxes */
+      int boundary_direction;
+      bool boundary_positive;
+
+      for(int d=0;d<dim;++d)
+        {
+          if(overlap_box.lower(d)-overlap_box.upper(d)==0)
+            {
+              boundary_direction=d;
+              if(fine_box.upper(d)<overlap_box.lower(d))
+                boundary_positive=true;
+              else if(fine_box.lower(d)>overlap_box.upper(d))
+                boundary_positive=false;
+              else
+                abort();
+              break;
+            }
+        }
+
+      hier::Index p_min(dimension), p_max(dimension);
+      for(int d=0;d<dim;++d)
+        {
+          p_min[d]=std::max(overlap_box.lower(d),gbox.lower(d));
+          p_max[d]=std::min(overlap_box.upper(d),gbox.upper(d));
+        }
+
+      hier::Index ip(hier::Index::getZeroIndex(dimension)), jp(ip), kp(ip);
+      ip[0]=1;
+      jp[1]=1;
+      if(dim>2)
+        kp[2]=1;
+
+      if(dim==2)
+        {
+          /* This odd stride is because we handle all of the fine
+           * boundary cells in a coarse cell at once.  However,
+           * sometimes there is only one fine cell in a coarse cell,
+           * so the starting point does not align with the coarse
+           * cell.  The stride ensures that, if we start not aligned,
+           * the next step will be aligned. */
+
+          for(int j=p_min[1]; j<=p_max[1]; j=(j/2)*2+2)
+            for(int i=p_min[0]; i<=p_max[0]; i=(i/2)*2+2)
+              {
+                pdat::CellIndex fine(hier::Index(i,j));
+        
+                switch(boundary_direction)
+                  {
+                  case 0:
+                    Update_P_2D(fine,boundary_positive ? ip : -ip,jp,j,p_max[1],
+                                *p,*p_fine);
+                    break;
+                  case 1:
+                    Update_P_2D(fine,boundary_positive ? jp : -jp,ip,i,p_max[0],
+                                *p,*p_fine);
+                    break;
+                  }
+              }
+        }
+      else
+        {
+          for(int k=p_min[2]; k<=p_max[2]; ++k)
+            for(int j=p_min[1]; j<=p_max[1]; ++j)
+              for(int i=p_min[0]; i<=p_max[0]; ++i)
+                {
+                  pdat::CellIndex fine(hier::Index(i,j,k));
+        
+                  switch(boundary_direction)
+                    {
+                    case 0:
+                      Update_P_3D(fine,boundary_positive ? ip : -ip,jp,kp,
+                                  j,k,p_max[1],p_max[2],*p,*p_fine);
+                      break;
+                    case 1:
+                      Update_P_3D(fine,boundary_positive ? jp : -jp,kp,ip,
+                                  k,i,p_max[2],p_max[0],*p,*p_fine);
+                      break;
+                    case 2:
+                      Update_P_3D(fine,boundary_positive ? kp : -kp,ip,jp,
+                                  i,j,p_max[0],p_max[1],*p,*p_fine);
+                      break;
+                    }
+                }
+        }
+    }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/P_Refine.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/P_Refine.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,115 @@
+/*************************************************************************
+ *
+ * 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:   Linear refine operator for cell-centered double data on
+ *                a Cartesian mesh. 
+ *
+ ************************************************************************/
+
+#include "P_Refine.h"
+
+#include <float.h>
+#include <math.h>
+#include "SAMRAI/geom/CartesianPatchGeometry.h"
+#include "SAMRAI/hier/Index.h"
+#include "SAMRAI/pdat/CellData.h"
+#include "SAMRAI/pdat/CellVariable.h"
+#include "SAMRAI/tbox/Utilities.h"
+
+void SAMRAI::geom::Elastic::P_Refine::refine(
+   hier::Patch& fine,
+   const hier::Patch& coarse,
+   const int dst_component,
+   const int src_component,
+   const hier::BoxOverlap& fine_overlap,
+   const hier::IntVector& ratio) const
+{
+   const pdat::CellOverlap* t_overlap =
+      dynamic_cast<const pdat::CellOverlap *>(&fine_overlap);
+
+   TBOX_ASSERT(t_overlap != NULL);
+
+   const hier::BoxList& boxes = t_overlap->getDestinationBoxList();
+   for (hier::BoxList::Iterator b(boxes); b; b++) {
+      refine(fine,
+         coarse,
+         dst_component,
+         src_component,
+         b(),
+         ratio);
+   }
+}
+
+void SAMRAI::geom::Elastic::P_Refine::refine(
+   hier::Patch& fine_patch,
+   const hier::Patch& coarse_patch,
+   const int dst_component,
+   const int src_component,
+   const hier::Box& fine_box,
+   const hier::IntVector& ratio) const
+{
+   const tbox::Dimension& dim(getDim());
+   TBOX_DIM_ASSERT_CHECK_DIM_ARGS4(dim, fine_patch, coarse_patch,
+                                   fine_box, ratio);
+
+   tbox::Pointer<pdat::CellData<double> >
+   p = coarse_patch.getPatchData(src_component);
+   tbox::Pointer<pdat::CellData<double> >
+   p_fine = fine_patch.getPatchData(dst_component);
+#ifdef DEBUG_CHECK_ASSERTIONS
+   TBOX_ASSERT(!p.isNull());
+   TBOX_ASSERT(!p_fine.isNull());
+   TBOX_ASSERT(p->getDepth() == p_fine->getDepth());
+#endif
+
+   hier::Box coarse_box=coarse_patch.getBox();
+   tbox::Pointer<geom::CartesianPatchGeometry>
+     geom = coarse_patch.getPatchGeometry();
+
+   for(pdat::CellIterator ci(fine_box); ci; ci++)
+     {
+       pdat::CellIndex fine(*ci);
+
+       pdat::CellIndex
+         center(hier::Index::coarsen(fine,hier::Index::getOneIndex(dim)*2));
+
+       /* Pressure is cell-centered, so prolongation is a
+          linear interpolation from nearby cells. */
+
+       /* This assumes that the levels are always properly nested,
+          so that we always have an extra grid space for
+          interpolation.  So we only have to have a special case for
+          physical boundaries, where we do not have an extra grid
+          space. */
+
+       /* We could, in theory, use a refine_patch_strategy to fill
+          in the ghost zones with extrapolations, and then use
+          simple differences here. */
+
+       (*p_fine)(fine)=(*p)(center);
+       for(int d=0; d<dim.getValue(); ++d)
+         {
+           hier::Index ip(hier::Index::getZeroIndex(dim));
+           ip[d]=1;
+           double dp;
+           if(center[d]==coarse_box.lower(d)
+              && geom->getTouchesRegularBoundary(d,0))
+             {
+               dp=((*p)(center+ip)-(*p)(center))/4;
+             }
+           else if(center[d]==coarse_box.upper(d)
+                   && geom->getTouchesRegularBoundary(d,1))
+             {
+               dp=((*p)(center)-(*p)(center-ip))/4;
+             }
+           else
+             {
+               dp=((*p)(center+ip)-(*p)(center-ip))/8;
+             }
+           (*p_fine)(fine)+=((fine[d]%2==0) ? (-dp) : dp);
+         }           
+       }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/P_Refine.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/P_Refine.h	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,143 @@
+/*************************************************************************
+ *
+ * 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:   Linear refine operator for cell-centered double data on
+ *                a Cartesian mesh. 
+ *
+ ************************************************************************/
+
+#ifndef GAMRA_ELASTIC_P_REFINE_H
+#define GAMRA_ELASTIC_P_REFINE_H
+
+#include "SAMRAI/SAMRAI_config.h"
+
+#include "SAMRAI/xfer/RefineOperator.h"
+#include "SAMRAI/hier/Box.h"
+#include "SAMRAI/hier/IntVector.h"
+#include "SAMRAI/hier/Patch.h"
+#include "SAMRAI/tbox/Pointer.h"
+#include "SAMRAI/pdat/CellVariable.h"
+
+#include <string>
+
+namespace SAMRAI {
+namespace geom {
+namespace Elastic {
+/**
+ * Class P_Refine implements linear
+ * interpolation for cell-centered double patch data defined over a Cartesian
+ * mesh.  It is derived from the xfer::RefineOperator base class.
+ * CartesianCellDoubleLinearRefine does not handle the lack of real
+ * boundaries for the pressure very well, so use this instead for
+ * pressure.
+ *
+ * The findRefineOperator() operator function returns true if the input
+ * variable is cell-centered double, and the std::string is "P_REFINE".
+ *
+ * @see xfer::RefineOperator
+ */
+
+class P_Refine:
+  public xfer::RefineOperator
+{
+public:
+  /**
+   * Uninteresting default constructor.
+   */
+  explicit P_Refine(const tbox::Dimension& dim):
+    xfer::RefineOperator(dim, "P_REFINE")
+  {
+    d_name_id = "P_REFINE";
+  }
+
+
+  /**
+   * Uninteresting virtual destructor.
+   */
+  virtual ~P_Refine(){}
+
+  /**
+   * Return true if the variable and name std::string match cell-centered
+   * double linear interpolation; otherwise, return false.
+   */
+  bool findRefineOperator(const tbox::Pointer<hier::Variable>& var,
+                          const std::string& op_name) const
+  {
+    TBOX_DIM_ASSERT_CHECK_ARGS2(*this, *var);
+
+    const tbox::Pointer<pdat::CellVariable<double> > cast_var(var);
+    if (!cast_var.isNull() && (op_name == d_name_id)) {
+      return true;
+    } else {
+      return false;
+    }
+  }
+  /**
+   * Return name std::string identifier of this refinement operator.
+   */
+  const std::string& getOperatorName() const
+  {
+    return d_name_id;
+  }
+
+  /**
+   * The priority of cell-centered double linear interpolation is 0.
+   * It will be performed before any user-defined interpolation operations.
+   */
+  int getOperatorPriority() const
+  {
+    return 0;
+  }
+
+  /**
+   * The stencil width of the linear interpolation operator is the vector
+   * of ones.  That is, its stencil extends one cell outside the fine box.
+   */
+  hier::IntVector getStencilWidth() const
+  {
+    return hier::IntVector::getOne(getDim());
+  }
+
+  /**
+   * Refine the source component on the coarse patch to the destination
+   * component on the fine patch using the cell-centered double linear
+   * interpolation operator.  Interpolation is performed on the intersection
+   * of the destination patch and the boxes contained in fine_overlap
+   * It is assumed that the coarse patch contains sufficient data for the
+   * stencil width of the refinement operator.
+   */
+  void refine(hier::Patch& fine,
+              const hier::Patch& coarse,
+              const int dst_component,
+              const int src_component,
+              const hier::BoxOverlap& fine_overlap,
+              const hier::IntVector& ratio) const;
+
+  /**
+   * Refine the source component on the coarse patch to the destination
+   * component on the fine patch using the cell-centered double linear
+   * interpolation operator.  Interpolation is performed on the intersection
+   * of the destination patch and the fine box.   It is assumed that the
+   * coarse patch contains sufficient data for the stencil width of the
+   * refinement operator.  This differs from the above refine() method
+   * only in that it operates on a single fine box instead of a BoxOverlap.
+   */
+  void refine(hier::Patch& fine,
+              const hier::Patch& coarse,
+              const int dst_component,
+              const int src_component,
+              const hier::Box& fine_box,
+              const hier::IntVector& ratio) const;
+
+private:
+  std::string d_name_id;
+
+};
+
+}
+}
+}
+#endif
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/P_Refine_Patch_Strategy.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/P_Refine_Patch_Strategy.h	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,410 @@
+/*************************************************************************
+ *
+ * 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:   Robin boundary condition support on cartesian grids. 
+ *
+ ************************************************************************/
+#ifndef GAMRA_ELASTIC_P_REFINE_PATCH_STRATEGY_H
+#define GAMRA_ELASTIC_P_REFINE_PATCH_STRATEGY_H
+
+#include "SAMRAI/SAMRAI_config.h"
+
+#include "SAMRAI/xfer/RefinePatchStrategy.h"
+#include "SAMRAI/geom/CartesianPatchGeometry.h"
+#include "SAMRAI/pdat/CellData.h"
+#include "SAMRAI/pdat/CellIndex.h"
+#include "Constants.h"
+#include "set_boundary.h"
+
+namespace SAMRAI {
+namespace solv {
+namespace Elastic {
+
+/*!
+ * @brief Helper utility for setting boundary conditions on P.
+ *
+ * This class inherits and implements virtual functions from
+ * xfer::RefinePatchStrategy so it may be used to help create
+ * communication schedules if desired.
+ */
+class P_Refine_Patch_Strategy:
+   public xfer::RefinePatchStrategy
+{
+
+public:
+   /*!
+    * @brief Constructor using.
+    *
+    * @param object_name Name of the object, for general referencing.
+    * @param coef_strategy Coefficients strategy being helped.
+    */
+   P_Refine_Patch_Strategy(
+      const tbox::Dimension& dim,
+      std::string object_name = std::string()):
+     xfer::RefinePatchStrategy(dim), d_dim(dim),d_object_name(object_name) {}
+
+   /*!
+    * @brief Destructor.
+    */
+   virtual ~P_Refine_Patch_Strategy(void) {}
+
+   //@{ @name xfer::RefinePatchStrategy virtuals
+
+   virtual void
+   setPhysicalBoundaryConditions(
+      hier::Patch& ,
+      const double ,
+      const hier::IntVector& ) {}
+   hier::IntVector
+   getRefineOpStencilWidth() const
+  { return hier::IntVector::getOne(d_dim); }
+   // virtual void
+   // preprocessRefineBoxes(
+   //    hier::Patch& fine,
+   //    const hier::Patch& coarse,
+   //    const hier::BoxList& fine_boxes,
+   //    const hier::IntVector& ratio) {}
+   virtual void
+   preprocessRefine(hier::Patch& ,
+                    const hier::Patch& coarse,
+                    const hier::Box& ,
+                    const hier::IntVector& )
+  {
+    set_boundary(coarse,p_id,invalid_id,true);
+  }
+
+   virtual void
+   postprocessRefineBoxes(
+      hier::Patch& ,
+      const hier::Patch& ,
+      const hier::BoxList& ,
+      const hier::IntVector& ) {}
+   virtual void
+   postprocessRefine(
+      hier::Patch& ,
+      const hier::Patch& ,
+      const hier::Box& ,
+      const hier::IntVector& ) {}
+
+   //@}
+
+   //@{
+
+   /*!
+    * @name Functions to set boundary condition values
+    */
+
+   /*!
+    * @brief Set the physical boundary condition by setting the
+    * value of the first ghost cells.
+    *
+    * This function has an interface similar to the virtual function
+    * xfer::RefinePatchStrategy::setPhysicalBoundaryConditions(),
+    * and it may be used to help implement that function,
+    * but it does not serve the same purpose.  The primary
+    * differences are:
+    * -# It specializes to cell-centered variables.
+    * -# Only one ghost cell width is filled.  Setting a Robin
+    *    boundary condition for cell-centered quantities requires
+    *    only one ghost cell to be set.
+    *    (More ghost cells can be filled by continuing the linear
+    *    distribution of data beyond the first cell, but that is
+    *    not implemented at this time.)
+    * -# User must specify the index of the data whose ghost
+    *    cells need to be filled.  This index is used to determine
+    *    the variable for which to set the boundary coefficients
+    *    and to get the data to be set.
+    *
+    * This function calls RobinBcStrategy::setBcCoefs() to
+    * get the coefficients, then it sets the values in the first
+    * ghost cell on the boundary.
+    *
+    * To determine the value for the ghost cell,
+    * a @em linear approximation in the direction normal to the
+    * boundary is assumed.  We write the following discrete
+    * approximations:
+    * @f[ u_b = \frac{ u_i + u_o }{2} @f]
+    * @f[ [u_n]_b = \frac{ u_o - u_i }{h} @f]
+    * where the subscript b stands for the the boundary,
+    * i stands for the first cell inside the boundary and
+    * o stands for the first cell outside the boundary
+    * and h is the grid spacing normal to the boundary.
+    * Applying this to the Robin formula gives
+    * @f[ u_o = \frac{ h\gamma + u_i( \beta - \frac{h}{2} \alpha ) }
+    * { \beta + \frac{h}{2} \alpha } @f] or equivalently
+    * @f[ u_o = \frac{ hg + u_i (1-a(1+\frac{h}{2})) }{ 1-a(1-\frac{h}{2}) } @f]
+    *
+    * After setting the edge (face in 3D) boundary conditions,
+    * linear approximations are used to set the boundary conditions
+    * of higher boundary types (nodes in 2D, edges and nodes in 3D).
+    *
+    * In some cases, the calling function wants to set the
+    * boundary condition homogeneously, with g=0.
+    * This is useful in problems where the the solution of the
+    * homogeneous problem is required in solving the inhomogeneous
+    * problem.  This function respects such requests specified
+    * through the argument @c homogeneous_bc.
+    *
+    * @internal To be more general to other data types,
+    * there could be versions for other data types also,
+    * such as ...InNodes, ...InFaces, etc.  However, I'm not
+    * sure exactly how to implement the Robin boundary condition
+    * on the faces and nodes when m != 1.  Should the boundary
+    * value be set or should the first ghost value be set?
+    *
+    * @internal I have not addressed possibility of differences
+    * in chosing the discrete formulation with which to compute
+    * the boundary value.  The above formulation is obviously
+    * one specific approximation, but there could be others.
+    * If anoter approximation is required, there should be
+    * another class like this or this class can offer a choice
+    * to be set by the user.  I favor another class.
+    *
+    * @internal Since the data alignment can be found through
+    * the target_data_id, these types of functions may be changed
+    * to just plain setBoundaryValues or setBoundaryValuesInBoundaryBoxes
+    * since it does assume boundary boxes.  This may have to be
+    * expanded to later include coarse-fine boundary boxes
+    * for more generality.
+    *
+    * @param patch hier::Patch on which to set boundary condition
+    * @param fill_time Solution time corresponding to filling
+    * @param ghost_width_to_fill Max ghost width requiring fill
+    * @param target_data_id hier::Patch data index of data to be set.
+    *        This data must be a cell-centered double.
+    * @param homogeneous_bc Set a homogeneous boundary condition.
+    *    This means g=0 for the boundary.
+    */
+   // void
+   // setBoundaryValuesInCells(
+   //    hier::Patch& patch,
+   //    const double fill_time,
+   //    const hier::IntVector& ghost_width_to_fill,
+   //    int target_data_id,
+   //    bool homogeneous_bc = false) const;
+
+   /*!
+    * @brief Set ghost cells for an entire level.
+    *
+    * Loop through all patches on the given level and call
+    * setBoundaryValuesInCells(hier::Patch &patch,
+    *                          const double fill_time ,
+    *                          const hier::IntVector &ghost_width_to_fill ,
+    *                          int target_data_id ,
+    *                          bool homogeneous_bc=false )
+    * for each.
+    *
+    * @param level PatchLevel on which to set boundary condition
+    * @param fill_time Solution time corresponding to filling
+    * @param ghost_width_to_fill Max ghost width requiring fill
+    * @param target_data_id hier::Patch data index of data to be set.
+    *        This data must be a cell-centered double.
+    * @param homogeneous_bc Set a homogeneous boundary condition.
+    *    This means g=0 for the boundary.
+    */
+   // void
+   // setBoundaryValuesInCells(
+   //    hier::PatchLevel& level,
+   //    const double fill_time,
+   //    const hier::IntVector& ghost_width_to_fill,
+   //    int target_data_id,
+   //    bool homogeneous_bc = false) const;
+
+   /*!
+    * @brief Set the physical boundary condition by setting the
+    * value of the boundary nodes.
+    *
+    * This function is not yet implemented!
+    *
+    * There are some decisions that must be made before
+    * the implementation can be written.
+    * -# Do we set the values on the boundary or one cell
+    *    away from the boundary?
+    * -# What is the discrete formulation we should use
+    *    to compute the value to be set?
+    *
+    * This function has an interface similar to the virtual function
+    * xfer::RefinePatchStrategy::setPhysicalBoundaryConditions(),
+    * and it may be used to help implement that function,
+    * but it does not serve the same purpose.  The primary
+    * differences are:
+    * -# It specializes to node-centered variables.
+    * -# User must specify the index of the data whose ghost
+    *    cells need to be filled.  This index is used to determine
+    *    the variable for which to set the boundary coefficients
+    *    and to get the data to be set.
+    *
+    * This function calls RobinBcStrategy::setBcCoefs() to get the
+    * coefficients, then it sets the values at the boundary nodes.
+    *
+    * In some cases, the calling function wants to set the
+    * boundary condition homogeneously, with g=0.
+    * This is useful in problems where the the solution of the
+    * homogeneous problem is required to solving the inhomogeneous
+    * problem.  This function respects such requests specified
+    * through the argument @c homogeneous_bc.
+    *
+    * @param patch hier::Patch on which to set boundary condition
+    * @param fill_time Solution time corresponding to filling
+    * @param target_data_id hier::Patch data index of data to be set.
+    * @param homogeneous_bc Set a homogeneous boundary condition.
+    *    This means g=0 for the boundary.
+    */
+   // void
+   // setBoundaryValuesAtNodes(
+   //    hier::Patch& patch,
+   //    const double fill_time,
+   //    int target_data_id,
+   //    bool homogeneous_bc = false) const;
+
+   //@}
+
+   //@{
+   /*!
+    * @name Ways to provide the Robin bc coefficients
+    */
+
+   /*!
+    * @brief Provide an implementation of the RobinBcCoefStrategy
+    * for determining the boundary coefficients.
+    *
+    * Provide the implementation that can be used to set the
+    * Robin bc coefficients.
+    *
+    * @param coef_strategy tbox::Pointer to a concrete inmplementation of
+    *        the coefficient strategy.
+    */
+   // void
+   // setCoefImplementation(
+   //    const RobinBcCoefStrategy* coef_strategy);
+
+   /*!
+    * @brief Set the data id that should be filled when setting
+    * physical boundary conditions.
+    *
+    * When setPhysicalBoundaryConditions is called, the data
+    * specified will be set.  This information is required because
+    * the it is not passed in through the argument list of
+    * setPhysicalBounaryConditions.
+    */
+  void setTargetDataId(int id)
+  {
+    p_id=id;
+  }
+
+   /*!
+    * @brief Set whether boundary filling should assume homogeneous
+    * conditions.
+    *
+    * In certain circumstances, only the value of a is needed, while
+    * the value of g is temporarily not required and taken to be zero.
+    * (An example is in setting the boundary condition for error
+    * value in an iterative method.)  In such cases, use this function
+    * to set a flag that will cause a null pointer to be given to
+    * setBcCoefs() to indicate that fact.
+    */
+   // void
+   // setHomogeneousBc(
+   //    bool homogeneous_bc);
+
+   //@}
+
+private:
+   /*!
+    * @brief Trim a boundary box so that it does not stick out
+    * past a given box.
+    *
+    * Certain boundary-related operations occur on patch data that
+    * do not or cannot extend past the edgr or corner of a patch.
+    * This function is used to trim down the parts of the boundary box
+    * that extend past those points so that a suitable index range
+    * is achieved.
+    *
+    * The boundary box trimmed must be of type 1 or 2.
+    *
+    * @param boundary_box Boundary box to be trimmed.
+    * @param limit_box hier::Box to not stick past
+    *
+    * @return New trimmed boundary box.
+    */
+   // hier::BoundaryBox
+   // trimBoundaryBox(
+   //    const hier::BoundaryBox& boundary_box,
+   //    const hier::Box& limit_box) const;
+
+   /*!
+    * @brief Return box describing the index space of boundary nodes
+    * defined by a boundary box.
+    *
+    * Define a box describing the indices of the nodes corresponding
+    * to the input boundary box.  These nodes lie on the boundary
+    * itself.
+    *
+    * The input boundary_box must be of type 1
+    * (see hier::BoundaryBox::getBoundaryType()).
+    *
+    * @param boundary_box input boundary box
+    * @return a box to define the node indices corresponding to
+    *   boundary_box
+    */
+   // hier::Box
+   // makeNodeBoundaryBox(
+   //    const hier::BoundaryBox& boundary_box) const;
+
+   /*!
+    * @brief Return box describing the index space of faces
+    * defined by a boundary box.
+    *
+    * Define a box describing the indices of the codimension 1
+    * surface corresponding to the input boundary box.
+    *
+    * The input boundary_box must be of type 1
+    * (see hier::BoundaryBox::getBoundaryType()).
+    *
+    * This is a utility function for working with the
+    * indices coresponding to a boundary box but coincide
+    * with the patch boundary.
+    *
+    * @param boundary_box input boundary box
+    * @return a box to define the face indices corresponding to
+    *    boundary_box
+    */
+   // hier::Box
+   // makeFaceBoundaryBox(
+   //    const hier::BoundaryBox& boundary_box) const;
+
+   const tbox::Dimension d_dim;
+
+   std::string d_object_name;
+
+   /*!
+    * @brief Coefficient strategy giving a way to get to
+    * Robin bc coefficients.
+    */
+   // const RobinBcCoefStrategy* d_coef_strategy;
+
+   /*!
+    * @brief hier::Index of target patch data when filling ghosts.
+    */
+   int p_id;
+
+   /*!
+    * @brief Whether to assumg g=0 when filling ghosts.
+    */
+   // bool d_homogeneous_bc;
+
+   /*!
+    * @brief Timers for performance measurement.
+    */
+   // tbox::Pointer<tbox::Timer> t_set_boundary_values_in_cells;
+   // tbox::Pointer<tbox::Timer> t_use_set_bc_coefs;
+};
+
+}
+}
+}
+
+#endif  // included_solv_P_Refine_Patch_Strategy
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/Resid_Coarsen.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/Resid_Coarsen.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,54 @@
+#include "Resid_Coarsen.h"
+
+/**
+ * Coarsens using the moduli as weights.  So in 2D
+   resid_coarse = (resid(i,j)*moduli(i,j)
+                   + resid(i,j+1)*moduli(i,j+1)
+                   + resid(i+1,j)*moduli(i+1,j)
+                   + resid(i+1,j+1)*moduli(i+1,j+1))/(4*moduli_coarse)
+ */
+
+void SAMRAI::geom::Elastic::Resid_Coarsen::coarsen
+(hier::Patch& coarse,
+ const hier::Patch& fine,
+ const int dst_component,
+ const int src_component,
+ const hier::Box& coarse_box,
+ const hier::IntVector& ratio) const
+{
+  const tbox::Dimension& dimension(getDim());
+  TBOX_DIM_ASSERT_CHECK_DIM_ARGS4(dimension, coarse, fine, coarse_box, ratio);
+  
+  tbox::Pointer<pdat::CellData<double> >
+    r_fine_ptr = fine.getPatchData(src_component);
+  pdat::CellData<double> &r_fine(*r_fine_ptr);
+  tbox::Pointer<pdat::CellData<double> >
+    r_ptr = coarse.getPatchData(dst_component);
+  pdat::CellData<double> &r(*r_ptr);
+  tbox::Pointer<pdat::CellData<double> >
+    cell_moduli_fine_ptr = fine.getPatchData(cell_moduli_id);
+  pdat::CellData<double> &cell_moduli_fine(*cell_moduli_fine_ptr);
+
+  TBOX_ASSERT(!r_ptr.isNull());
+  TBOX_ASSERT(!r_fine_ptr.isNull());
+  TBOX_ASSERT(r_fine.getDepth() == r.getDepth());
+  TBOX_ASSERT(r.getDepth() == 1);
+
+  hier::Box cell_box(hier::Index::getZeroIndex(dimension),
+                     hier::Index::getOneIndex(dimension));
+
+  for(pdat::CellIterator ci(coarse.getBox()); ci; ci++)
+    {
+      pdat::CellIndex coarse(*ci);
+      pdat::CellIndex fine(coarse*2);
+      double temp(0), moduli_sum(0);
+
+      for(pdat::CellIterator ii(cell_box); ii; ii++)
+        {
+          pdat::CellIndex i(*ii);
+          temp+=r_fine(fine+i)*(cell_moduli_fine(fine+i,0)+cell_moduli_fine(fine+i,1));
+          moduli_sum+=(cell_moduli_fine(fine+i,0)+cell_moduli_fine(fine+i,1));
+        }
+      r(coarse)=temp/moduli_sum;
+    }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/Resid_Coarsen.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/Resid_Coarsen.h	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,77 @@
+#ifndef GAMRA_ELASTIC_Resid_Coarsen_H
+#define GAMRA_ELASTIC_Resid_Coarsen_H
+
+#include "SAMRAI/xfer/CoarsenOperator.h"
+#include "SAMRAI/pdat/CellVariable.h"
+#include <string>
+
+namespace SAMRAI {
+namespace geom {
+namespace Elastic {
+/**
+ * Coarsens using the moduli as weights.  So in 2D
+   resid_coarse = (resid(i,j)*moduli(i,j)
+                   + resid(i,j+1)*moduli(i,j+1)
+                   + resid(i+1,j)*moduli(i+1,j)
+                   + resid(i+1,j+1)*moduli(i+1,j+1))/(4*moduli_coarse)
+ * @see xfer::CoarsenOperator
+ */
+
+class Resid_Coarsen:
+   public xfer::CoarsenOperator
+{
+public:
+  explicit Resid_Coarsen(const tbox::Dimension& dim,
+                         const int &cell_moduli):
+    xfer::CoarsenOperator(dim, "RESID_COARSEN"),
+    cell_moduli_id(cell_moduli)
+  {
+    d_name_id = "RESID_COARSEN";
+  }
+
+  virtual ~Resid_Coarsen(){}
+
+  bool findCoarsenOperator(const tbox::Pointer<hier::Variable>& var,
+                           const std::string& op_name) const
+  {
+    TBOX_DIM_ASSERT_CHECK_ARGS2(*this, *var);
+
+    const tbox::Pointer<pdat::CellVariable<double> > cast_var(var);
+    if (!cast_var.isNull() && (op_name == d_name_id)) {
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  const std::string& getOperatorName() const
+  {
+    return d_name_id;
+  }
+
+  int getOperatorPriority() const
+  {
+    return 0;
+  }
+
+  hier::IntVector getStencilWidth() const
+  {
+    return hier::IntVector::getZero(getDim());
+  }
+
+  void coarsen(hier::Patch& coarse,
+               const hier::Patch& fine,
+               const int dst_component,
+               const int src_component,
+               const hier::Box& coarse_box,
+               const hier::IntVector& ratio) const;
+
+private:
+  std::string d_name_id;
+  const int cell_moduli_id;
+};
+
+}
+}
+}
+#endif
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/V_Boundary_Refine.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/V_Boundary_Refine.h	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,166 @@
+/*************************************************************************
+ *
+ * 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:   Linear refine operator for side-centered double data on
+ *                a Cartesian mesh. 
+ *
+ ************************************************************************/
+
+#ifndef GAMRA_ELASTIC_V_BOUNDARY_REFINE_H
+#define GAMRA_ELASTIC_V_BOUNDARY_REFINE_H
+
+#include "SAMRAI/SAMRAI_config.h"
+
+#include "SAMRAI/xfer/RefineOperator.h"
+#include "SAMRAI/hier/Box.h"
+#include "SAMRAI/hier/IntVector.h"
+#include "SAMRAI/hier/Patch.h"
+#include "SAMRAI/tbox/Pointer.h"
+#include "SAMRAI/pdat/SideVariable.h"
+#include "SAMRAI/geom/CartesianPatchGeometry.h"
+
+#include <string>
+
+namespace SAMRAI {
+namespace geom {
+namespace Elastic {
+
+/**
+ * Class V_Boundary_Refine implements the special interpolation needed
+ * for the boundary elements on the coarse-fine interface.
+ *
+ * The findRefineOperator() operator function returns true if the input
+ * variable is side-centered double, and the std::string is "V_BOUNDARY_REFINE".
+ *
+ * @see xfer::RefineOperator
+ */
+
+class V_Boundary_Refine:
+  public xfer::RefineOperator
+{
+public:
+  /**
+   * Uninteresting default constructor.
+   */
+  explicit V_Boundary_Refine(const tbox::Dimension& dim):
+    xfer::RefineOperator(dim, "V_BOUNDARY_REFINE")
+  {
+    d_name_id = "V_BOUNDARY_REFINE";
+  }
+
+
+  /**
+   * Uninteresting virtual destructor.
+   */
+  virtual ~V_Boundary_Refine(){}
+
+  /**
+   * Return true if the variable and name std::string match side-centered
+   * double linear interpolation; otherwise, return false.
+   */
+  bool findRefineOperator(const tbox::Pointer<hier::Variable>& var,
+                          const std::string& op_name) const
+  {
+    TBOX_DIM_ASSERT_CHECK_ARGS2(*this, *var);
+
+    const tbox::Pointer<pdat::SideVariable<double> > cast_var(var);
+    if (!cast_var.isNull() && (op_name == d_name_id)) {
+      return true;
+    } else {
+      return false;
+    }
+  }
+  /**
+   * Return name std::string identifier of this refinement operator.
+   */
+  const std::string& getOperatorName() const
+  {
+    return d_name_id;
+  }
+
+  /**
+   * The priority of side-centered double linear interpolation is 0.
+   * It will be performed before any user-defined interpolation operations.
+   */
+  int getOperatorPriority() const
+  {
+    return 0;
+  }
+
+  /**
+   * The stencil width of the linear interpolation operator is the vector
+   * of ones.  That is, its stencil extends one side outside the fine box.
+   */
+  hier::IntVector getStencilWidth() const
+  {
+    return hier::IntVector::getOne(getDim());
+  }
+
+  /**
+   * Refine the source component on the coarse patch to the destination
+   * component on the fine patch using the side-centered double linear
+   * interpolation operator.  Interpolation is performed on the intersection
+   * of the destination patch and the boxes contained in fine_overlap
+   * It is assumed that the coarse patch contains sufficient data for the
+   * stencil width of the refinement operator.
+   */
+  void refine(hier::Patch& fine,
+              const hier::Patch& coarse,
+              const int dst_component,
+              const int src_component,
+              const hier::BoxOverlap& fine_overlap,
+              const hier::IntVector& ratio) const;
+
+  /**
+   * Refine the source component on the coarse patch to the destination
+   * component on the fine patch using the side-centered double linear
+   * interpolation operator.  Interpolation is performed on the intersection
+   * of the destination patch and the fine box.   It is assumed that the
+   * coarse patch contains sufficient data for the stencil width of the
+   * refinement operator.  This differs from the above refine() method
+   * only in that it operates on a single fine box instead of a BoxOverlap.
+   */
+  void refine(hier::Patch& fine,
+              const hier::Patch& coarse,
+              const int dst_component,
+              const int src_component,
+              const hier::Box& fine_box,
+              const hier::IntVector& ratio,
+              const int &axis) const;
+
+private:
+  std::string d_name_id;
+
+  void Update_V_2D
+  (const int &axis,
+   const int &boundary_direction,
+   const bool &boundary_positive,
+   const pdat::SideIndex &fine,
+   const hier::Index &ip, const hier::Index &jp,
+   int &i, int &j,
+   const int &i_max,
+   const int &j_min,
+   const int &j_max,
+   pdat::SideData<double> &v,
+   pdat::SideData<double> &v_fine) const;
+
+  void Update_V_3D
+  (const int &axis,
+   const int &boundary_direction,
+   const bool &boundary_positive,
+   const pdat::SideIndex &fine,
+   const hier::Index pp[],
+   const hier::Index &ijk,
+   const hier::Index &p_min, const hier::Index &p_max,
+   SAMRAI::pdat::SideData<double> &v,
+   SAMRAI::pdat::SideData<double> &v_fine) const;
+
+};
+
+}
+}
+}
+#endif
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/V_Boundary_Refine/Update_V_2D.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/V_Boundary_Refine/Update_V_2D.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,155 @@
+#include "Elastic/V_Boundary_Refine.h"
+#include "quad_offset_interpolate.h"
+#include "Constants.h"
+
+/* This is written from the perspective of axis==x.  For axis==y, we
+   switch i and j and everything works out. */
+void SAMRAI::geom::Elastic::V_Boundary_Refine::Update_V_2D
+(const int &axis,
+ const int &boundary_direction,
+ const bool &boundary_positive,
+ const pdat::SideIndex &fine,
+ const hier::Index &ip, const hier::Index &jp,
+ int &i, int &j,
+ const int &i_max,
+ const int &j_min,
+ const int &j_max,
+ SAMRAI::pdat::SideData<double> &v,
+ SAMRAI::pdat::SideData<double> &v_fine) const
+{
+  /* Set the derivative for the normal direction
+
+         i-1      i       i+1
+
+        ------- -------
+       |   f   f   F   |
+   j-1 C       C       C
+       |   f   f   F   |
+        ------- -------
+       |   f   f   F   |
+   j   C       C       C
+       |   f   f   F   |
+        ------- -------
+       |   f   f   F   |
+   j+1 C       C       C
+       |   f   f   F   |
+        ------- -------
+               |
+               |
+               |
+        Coarse-Fine Boundary
+
+    So we need to set F such that the derivative at the coarse-fine
+    boundary is coorrect.  We can compute the derivative at the coarse
+    points on the boundary, and then use quadratic interpolation to
+    get the derivative at the fine points on the boundary.
+
+ */
+  if(boundary_direction==axis)
+    {
+      /* Return early if we are at j==j_max, because that is a corner
+         that we do not care about.  We could also skip if j==j_min as
+         long as we do not have to do j_min+1. We do not really have
+         to skip these since we are guaranteed to have valid data for
+         those "past the end" points since they are needed for
+         pressure refinement.  */
+      if(j==j_max || (j==j_min && j%2!=0))
+        return;
+      /* Compute the derivative at the nearest three coarse points and
+         then interpolate */
+
+      hier::Index ip_s(boundary_positive ? ip : -ip);
+
+      pdat::SideIndex center(fine-ip_s);
+      center.coarsen(hier::Index(2,2));
+
+      const double dv_plus=v(center+jp+ip_s)-v(center+jp-ip_s);
+      const double dv_minus=v(center-jp+ip_s)-v(center-jp-ip_s);
+      const double dv_center=v(center+ip_s)-v(center-ip_s);
+
+      double dv_fine_minus, dv_fine_plus;
+
+      quad_offset_interpolate(dv_plus,dv_center,dv_minus,
+                              dv_fine_plus,dv_fine_minus);
+
+      hier::Index offset(ip_s*2);
+
+      if(j%2==0)
+        {
+          v_fine(fine)=v_fine(fine-offset) + dv_fine_minus/2;
+          v_fine(fine+jp)=v_fine(fine-offset+jp) + dv_fine_plus/2;
+          /* Since we update two points on j at once, we increment j
+             again.  This is ok, since the box in the 'i' direction is
+             defined to be only one cell wide */
+          ++j;
+        }
+      else
+        {
+          v_fine(fine)=v_fine(fine-offset) + dv_fine_plus/2;
+        }          
+    }
+  /* Set the value for the tangential direction
+
+         i-1      i       i+1
+
+        -f-C-f- -F-C---    C
+       |       |       |
+   j-1 |       |       |    
+       |       |       |
+        -f-C-f- -F-C---    C
+       |       |       |
+   j   |       |       |    
+       |       |       |
+        -f-C-f- -F-C---    C
+       |       |       |
+   j+1 |       |       |    
+       |       |       |
+        -f-C-f- -F-C---    C
+               |
+               |
+               |
+        Coarse-Fine Boundary
+
+    C are the coarse velocities, f are the interior fine velocities,
+    and F are the boundary fine velocities that we need to set.  So we
+    use quadratic interpolation from C to F.
+ */
+  else
+    {
+      pdat::SideIndex center(fine);
+      center.coarsen(hier::Index(2,2));
+
+      double v_center, v_plus;
+      hier::Index jp_s(boundary_positive ? jp : -jp);
+
+      v_center=
+        quad_offset_interpolate(v(center-jp_s),v(center),v(center+jp_s));
+
+      if(i%2==0)
+        {
+          v_fine(fine)=v_center;
+
+          if(i<i_max)
+            {
+              /* This is a bit inefficient, because we compute v_plus
+               * twice.  Once for the in-between point, and again
+               * later for the actual point. */
+
+              v_plus=quad_offset_interpolate(v(center+ip-jp_s),v(center+ip),
+                                             v(center+ip+jp_s));
+              v_fine(fine+ip)=(v_center+v_plus)/2;
+
+              /* Since we update two points on 'i' at once, we increment 'i' again.
+                 This is ok, since the box in the 'j' direction is defined to be
+                 only one cell wide */
+              ++i;
+            }
+        }
+      else
+        {
+          v_plus=quad_offset_interpolate(v(center+ip-jp_s),v(center+ip),
+                                         v(center+ip+jp_s));
+          v_fine(fine)=(v_center+v_plus)/2;
+        }
+    }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/V_Boundary_Refine/Update_V_3D.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/V_Boundary_Refine/Update_V_3D.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,251 @@
+#include "Elastic/V_Boundary_Refine.h"
+#include "Constants.h"
+
+/* This is written from the perspective of axis==x.  For axis==y, we
+   switch i and j and everything works out. */
+void SAMRAI::geom::Elastic::V_Boundary_Refine::Update_V_3D
+(const int &axis,
+ const int &boundary_direction,
+ const bool &boundary_positive,
+ const pdat::SideIndex &fine,
+ const hier::Index pp[],
+ const hier::Index &ijk,
+ const hier::Index &p_min, const hier::Index &p_max,
+ SAMRAI::pdat::SideData<double> &v,
+ SAMRAI::pdat::SideData<double> &v_fine) const
+{
+  /* Set the derivative for the normal direction.
+
+     We set the derivative on the i=constant plane.  If we look at a
+     slice in that plane.
+
+         k-1      k       k+1
+
+        ------- -------
+       |       |       |
+   j-1 |   D   |   D   |   D
+       |       |       |
+        ------- -------
+       |       |d-- d+-|
+   j   |   D   |   D   |   D
+       |       |d-+ d++|
+        ------- -------
+       |       |       |
+   j+1 |   D   |   D   |   D
+       |       |       |
+        ------- -------
+               |
+               |
+               |
+        Coarse-Fine Boundary
+
+  where D are the coarse derivatives, and d are the fine derivatives.
+  This picture is the same as what is seen in P_Boundary_Refine in 2D.
+  So we can use the formula there to compute d--.
+
+   d(-,-) = a - b/4 + c/16 - d/4 + e/16 + f/16
+          = D(-,-)/16 + (15/16)*D(0,0)
+            + (3/32)*(-D(+,0) - D(0,+) + D(-,0) + D(0,-))
+
+  */
+
+  if(boundary_direction==axis)
+    {
+      /* Return early if we are at j==j_max, because that is a corner
+         that we do not care about.  We also skip if j==j_min as long
+         as we do not have to do j_min+1. We have to skip these even
+         though they are not used because otherwise we could end up
+         reading past the end of the array.  */
+      const int axis2((axis+1)%3), axis3((axis+2)%3);
+      if(ijk[axis2]==p_max[axis2] || (ijk[axis2]==p_min[axis2] && ijk[axis2]%2!=0)
+         || ijk[axis3]==p_max[axis3] 
+         || (ijk[axis3]==p_min[axis3] && ijk[axis3]%2!=0))
+        return;
+      /* Compute the derivative at all of the interpolation points.  */
+
+      const hier::Index ip(boundary_positive ? pp[axis] : -pp[axis]),
+        jp(pp[(axis+1)%3]), kp(pp[(axis+2)%3]);
+
+      pdat::SideIndex center(fine-ip);
+      center.coarsen(hier::Index(2,2,2));
+
+      const double dv_mm=v(center-jp-kp+ip) - v(center-jp-kp-ip);
+      const double dv_m0=v(center-jp+ip) - v(center-jp-ip);
+      const double dv_mp=v(center-jp+kp+ip) - v(center-jp+kp-ip);
+
+      const double dv_0m=v(center-kp+ip) - v(center-kp-ip);
+      const double dv_00=v(center+ip) - v(center-ip);
+      const double dv_0p=v(center+kp+ip) - v(center+kp-ip);
+
+      const double dv_pm=v(center+jp-kp+ip) - v(center+jp-kp-ip);
+      const double dv_p0=v(center+jp+ip) - v(center+jp-ip);
+      const double dv_pp=v(center+jp+kp+ip) - v(center+jp+kp-ip);
+
+      const double dv_fine_mm=dv_mm/16 + (15.0/16)*dv_00
+        + (3/32)*(-dv_p0 - dv_0p + dv_m0 + dv_0m);
+
+      const double dv_fine_mp=dv_mp/16 + (15.0/16)*dv_00
+        + (3/32)*(-dv_p0 - dv_0m + dv_m0 + dv_0p);
+
+      const double dv_fine_pm=dv_pm/16 + (15.0/16)*dv_00
+        + (3/32)*(-dv_m0 - dv_0p + dv_p0 + dv_0m);
+
+      const double dv_fine_pp=dv_pp/16 + (15.0/16)*dv_00
+        + (3/32)*(-dv_m0 - dv_0m + dv_p0 + dv_0p);
+
+      hier::Index offset(ip*2);
+
+      /* Be careful about using the right interpolation if the fine
+       * points are not aligned with the coarse points. */
+      if(ijk[axis2]%2==0)
+        {
+          if(ijk[axis3]%2==0)
+            {
+              v_fine(fine)=v_fine(fine-offset) + dv_fine_mm/2;
+              if(ijk[axis2]<p_max[axis2])
+                v_fine(fine+jp)=v_fine(fine-offset+jp) + dv_fine_pm/2;
+              if(ijk[axis3]<p_max[axis3])
+                v_fine(fine+kp)=v_fine(fine-offset+kp) + dv_fine_mp/2;
+              if(ijk[axis2]<p_max[axis2] && ijk[axis3]<p_max[axis3])
+                v_fine(fine+jp+kp)=v_fine(fine-offset+jp+kp) + dv_fine_pp/2;
+            }
+          else
+            {
+              v_fine(fine)=v_fine(fine-offset) + dv_fine_mp/2;
+              if(ijk[axis2]<p_max[axis2])
+                v_fine(fine+jp)=v_fine(fine-offset+jp) + dv_fine_pp/2;
+            }
+        }
+      else
+        {
+          if(ijk[axis3]%2==0)
+            {
+              v_fine(fine)=v_fine(fine-offset) + dv_fine_pm/2;
+              if(ijk[axis3]<p_max[axis3])
+                v_fine(fine+kp)=v_fine(fine-offset+kp) + dv_fine_pp/2;
+            }
+          else
+            {
+              v_fine(fine)=v_fine(fine-offset) + dv_fine_pp/2;
+            }
+        }          
+    }
+  /* Set the value for the tangential direction.
+
+     Again, if we look at a slice in the i=constant plane.
+
+          j-1      j      j+1
+
+        ------- -------
+       |       |       |
+   k-1 |   V   |   V   |   V
+       |       |       |
+        ------- -------
+       |       |v--    |
+   k   |   V   |   V   |   V
+       |       |v-+    |
+        ------- -------
+       |       |       |
+   k+1 |   V   |   V   |   V
+       |       |       |
+        ------- -------
+               |
+               |
+               |
+        Coarse-Fine Boundary
+
+  where V are the coarse velocities, and v are the fine velocities.
+  This picture is the same as what is seen in P_Boundary_Refine in 2D.
+  So we can use the formula there to compute v--.
+
+   v(-,-) = V(-,-)/16 + (15/16)*V(0,0)
+            + (3/32)*(-V(+,0) - V(0,+) + V(-,0) + V(0,-))
+
+ */
+  else
+    {
+      const int axis3((axis+1)%3 != boundary_direction ? (axis+1)%3 : (axis+2)%3);
+      const hier::Index ip(pp[axis]),
+        jp(boundary_positive ? pp[boundary_direction] : -pp[boundary_direction]),
+        kp(pp[axis3]);
+
+      pdat::SideIndex center(fine);
+      center.coarsen(hier::Index(2,2,2));
+
+      double v_minus=v(center-jp-kp)/16 + (15.0/16)*v(center)
+        + (3.0/32)*(-v(center+jp) - v(center+kp) + v(center-jp) + v(center-kp));
+      
+      double v_plus=v(center-jp+kp)/16 + (15.0/16)*v(center)
+        + (3.0/32)*(-v(center+jp) - v(center-kp) + v(center-jp) + v(center+kp));
+
+
+      /* Be careful about using the right interpolation if the fine
+       * points are not aligned with the coarse points. */
+      if(ijk[axis]%2==0)
+        {
+          if(ijk[axis3]%2==0)
+            {
+              v_fine(fine)=v_minus;
+              if(ijk[axis3]<p_max[axis3])
+                v_fine(fine+kp)=v_plus;
+              if(ijk[axis]<p_max[axis])
+                {
+                  double v_minus_off=v(center-jp-kp+ip)/16
+                    + (15.0/16)*v(center+ip)
+                    + (3.0/32)*(-v(center+jp+ip) - v(center+kp+ip)
+                                + v(center-jp+ip) + v(center-kp+ip));
+      
+                  double v_plus_off=v(center-jp+kp+ip)/16
+                    + (15.0/16)*v(center+ip)
+                    + (3.0/32)*(-v(center+jp+ip) - v(center-kp+ip)
+                                + v(center-jp+ip) + v(center+kp+ip));
+
+                  v_fine(fine+ip)=(v_minus+v_minus_off)/2;
+                  if(ijk[axis3]<p_max[axis3])
+                    v_fine(fine+ip+kp)=(v_plus+v_plus_off)/2;
+                }
+            }
+          else
+            {
+              v_fine(fine)=v_plus;
+              if(ijk[axis]<p_max[axis])
+                {
+                  double v_plus_off=v(center-jp+kp+ip)/16
+                    + (15.0/16)*v(center+ip)
+                    + (3.0/32)*(-v(center+jp+ip) - v(center-kp+ip)
+                                + v(center-jp+ip) + v(center+kp+ip));
+
+                  v_fine(fine+ip)=(v_plus+v_plus_off)/2;
+                }
+            }
+        }
+      else
+        {
+          if(ijk[axis3]%2==0)
+            {
+              double v_minus_off=v(center-jp-kp+ip)/16
+                + (15.0/16)*v(center+ip)
+                + (3.0/32)*(-v(center+jp+ip) - v(center+kp+ip)
+                            + v(center-jp+ip) + v(center-kp+ip));
+      
+              double v_plus_off=v(center-jp+kp+ip)/16
+                + (15.0/16)*v(center+ip)
+                + (3.0/32)*(-v(center+jp+ip) - v(center-kp+ip)
+                            + v(center-jp+ip) + v(center+kp+ip));
+
+              v_fine(fine)=(v_minus+v_minus_off)/2;
+              if(ijk[axis3]<p_max[axis3])
+                v_fine(fine+kp)=(v_plus+v_plus_off)/2;
+            }
+          else
+            {
+              double v_plus_off=v(center-jp+kp+ip)/16
+                + (15.0/16)*v(center+ip)
+                + (3.0/32)*(-v(center+jp+ip) - v(center-kp+ip)
+                            + v(center-jp+ip) + v(center+kp+ip));
+
+              v_fine(fine)=(v_plus+v_plus_off)/2;
+            }
+        }
+    }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/V_Boundary_Refine/refine.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/V_Boundary_Refine/refine.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,141 @@
+/*************************************************************************
+ *
+ * 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:   Linear refine operator for side-centered double data on
+ *                a Cartesian mesh. 
+ *
+ ************************************************************************/
+
+#include "Elastic/V_Boundary_Refine.h"
+#include "Elastic/set_boundary.h"
+#include "Constants.h"
+
+void SAMRAI::geom::Elastic::V_Boundary_Refine::refine
+(hier::Patch& fine,
+ const hier::Patch& coarse,
+ const int dst_component,
+ const int src_component,
+ const hier::BoxOverlap& fine_overlap,
+ const hier::IntVector& ratio) const
+{
+   const pdat::SideOverlap* t_overlap =
+      dynamic_cast<const pdat::SideOverlap *>(&fine_overlap);
+
+   TBOX_ASSERT(t_overlap != NULL);
+
+   set_boundary(coarse,invalid_id,src_component,true);
+
+   for(int axis=0; axis<getDim().getValue(); ++axis)
+     {
+       const hier::BoxList& boxes = t_overlap->getDestinationBoxList(axis);
+       for (hier::BoxList::Iterator b(boxes); b; b++)
+         {
+           refine(fine,coarse,dst_component,src_component,b(),ratio,axis);
+         }
+     }
+}
+
+void SAMRAI::geom::Elastic::V_Boundary_Refine::refine
+(hier::Patch& fine,
+ const hier::Patch& coarse,
+ const int dst_component,
+ const int src_component,
+ const hier::Box& overlap_box,
+ const hier::IntVector& ratio,
+ const int &axis) const
+{
+   const tbox::Dimension& dimension(getDim());
+   TBOX_DIM_ASSERT_CHECK_DIM_ARGS4(dimension, fine, coarse, overlap_box, ratio);
+   const int dim(dimension.getValue());
+
+   tbox::Pointer<pdat::SideData<double> >
+   v = coarse.getPatchData(src_component);
+   tbox::Pointer<pdat::SideData<double> >
+   v_fine = fine.getPatchData(dst_component);
+#ifdef DEBUG_CHECK_ASSERTIONS
+   TBOX_ASSERT(!v.isNull());
+   TBOX_ASSERT(!v_fine.isNull());
+   TBOX_ASSERT(v->getDepth() == v_fine->getDepth());
+   TBOX_ASSERT(v->getDepth() == 1);
+#endif
+
+   hier::Box fine_box=fine.getBox();
+
+   /* We have to infer where the boundary is from the boxes */
+   int boundary_direction;
+   bool boundary_positive(false);
+
+   for(int d=0;d<dim;++d)
+     {
+       if(std::abs(overlap_box.lower(d)-overlap_box.upper(d))==(axis==d ? 1 : 0))
+         {
+           boundary_direction=d;
+           if(fine_box.upper(d)<=overlap_box.lower(d))
+             boundary_positive=true;
+           else if(fine_box.lower(d)>=overlap_box.upper(d))
+             boundary_positive=false;
+           else
+             abort();
+           break;
+         }
+     }
+
+   hier::Index p_min(overlap_box.lower()), p_max(overlap_box.upper());
+
+   if(boundary_direction==axis)
+     {
+       if(boundary_positive)
+         {
+           p_min[axis]=p_max[axis];
+         }
+       else
+         {
+           p_max[axis]=p_min[axis];
+         }
+     }
+
+   hier::Index ip(hier::Index::getZeroIndex(dimension)), jp(ip), kp(ip);
+   ip[0]=1;
+   jp[1]=1;
+   if(dim>2)
+     kp[2]=1;
+
+   if(dim==2)
+     {
+       for(int j=p_min[1]; j<=p_max[1]; ++j)
+         for(int i=p_min[0]; i<=p_max[0]; ++i)
+           {
+             pdat::SideIndex fine(hier::Index(i,j),axis,pdat::SideIndex::Lower);
+             switch(axis)
+               {
+               case 0:
+                 Update_V_2D(axis,boundary_direction,boundary_positive,fine,
+                             ip,jp,i,j,p_max[0],p_min[1],p_max[1],*v,*v_fine);
+                 break;
+               case 1:
+                 Update_V_2D(axis,boundary_direction,boundary_positive,fine,
+                             jp,ip,j,i,p_max[1],p_min[0],p_max[0],*v,*v_fine);
+                 break;
+               default:
+                 abort();
+                 break;
+               }
+         }
+     }
+   else
+     {
+       hier::Index pp[]={ip,jp,kp};
+       hier::Index ijk(dimension);
+       for(ijk[2]=p_min[2]; ijk[2]<=p_max[2]; ijk[2]=(ijk[2]/2)*2+2)
+         for(ijk[1]=p_min[1]; ijk[1]<=p_max[1]; ijk[1]=(ijk[1]/2)*2+2)
+           for(ijk[0]=p_min[0]; ijk[0]<=p_max[0]; ijk[0]=(ijk[0]/2)*2+2)
+             {
+               pdat::SideIndex fine(ijk,axis,pdat::SideIndex::Lower);
+               Update_V_3D(axis,boundary_direction,boundary_positive,fine,
+                           pp,ijk,p_min,p_max,*v,*v_fine);
+             }
+     }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/V_Coarsen.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/V_Coarsen.h	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,149 @@
+/*************************************************************************
+ *
+ * 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:   Weighted averaging operator for side-centered double data on
+ *                a Cartesian mesh. 
+ *
+ ************************************************************************/
+
+#ifndef GAMRA_ELASTIC_V_COARSEN_H
+#define GAMRA_ELASTIC_V_COARSEN_H
+
+#include "SAMRAI/SAMRAI_config.h"
+
+#include "SAMRAI/xfer/CoarsenOperator.h"
+#include "SAMRAI/hier/Box.h"
+#include "SAMRAI/hier/IntVector.h"
+#include "SAMRAI/hier/Patch.h"
+#include "SAMRAI/tbox/Pointer.h"
+#include "SAMRAI/pdat/SideVariable.h"
+
+#include <string>
+
+namespace SAMRAI {
+namespace geom {
+namespace Elastic {
+
+/**
+ * Class V_Coarsen implements averaging 
+ * for side-centered double patch data defined over
+ * a Cartesian mesh.  It is derived from the xfer::CoarsenOperator base class.
+ * The numerical operations for theaveraging use FORTRAN numerical routines.
+ *
+ * CartesianSideDoubleWeightedAverage averages over the nearest two
+ * cells, which is not what we want for multigrid.  This averages over
+ * the nearest six points (in 2D).  The findCoarsenOperator() operator
+ * function returns true if the input variable is side-centered
+ * double, and the std::string is "V_COARSEN".
+ *
+ * @see xfer::CoarsenOperator
+ */
+
+class V_Coarsen:
+   public xfer::CoarsenOperator
+{
+public:
+  /**
+   * Uninteresting default constructor.
+   */
+  explicit V_Coarsen(const tbox::Dimension& dim):
+    xfer::CoarsenOperator(dim, "V_COARSEN")
+  {
+    d_name_id = "V_COARSEN";
+  }
+
+  /**
+   * Uninteresting virtual destructor.
+   */
+  virtual ~V_Coarsen(){}
+
+  /**
+   * Return true if the variable and name std::string match the side-centered
+   * double weighted averaging; otherwise, return false.
+   */
+  
+  bool findCoarsenOperator(const tbox::Pointer<hier::Variable>& var,
+                           const std::string& op_name) const
+  {
+    TBOX_DIM_ASSERT_CHECK_ARGS2(*this, *var);
+
+    const tbox::Pointer<pdat::SideVariable<double> > cast_var(var);
+    if (!cast_var.isNull() && (op_name == d_name_id)) {
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  /**
+   * Return name std::string identifier of this coarsening operator.
+   */
+  const std::string& getOperatorName() const
+  {
+    return d_name_id;
+  }
+
+  /**
+   * The priority of side-centered double weighted averaging is 0.
+   * It will be performed before any user-defined coarsen operations.
+   */
+  int getOperatorPriority() const
+  {
+    return 0;
+  }
+
+  hier::IntVector getStencilWidth() const
+  {
+    return hier::IntVector::getOne(getDim());
+  }
+
+  /**
+   * Coarsen the source component on the fine patch to the destination
+   * component on the coarse patch using the side-centered double weighted
+   * averaging operator.  Coarsening is performed on the intersection of
+   * the destination patch and the coarse box.  It is assumed that the
+   * fine patch contains sufficient data for the stencil width of the
+   * coarsening operator.
+   */
+  void
+  coarsen(hier::Patch& coarse,
+             const hier::Patch& fine,
+             const int dst_component,
+             const int src_component,
+             const hier::Box& coarse_box,
+             const hier::IntVector& ratio) const
+  {
+    if(getDim().getValue()==2)
+      coarsen_2D(coarse,fine,dst_component,src_component,coarse_box,ratio);
+    else
+      coarsen_3D(coarse,fine,dst_component,src_component,coarse_box,ratio);
+  }
+
+  void
+  coarsen_2D(hier::Patch& coarse,
+             const hier::Patch& fine,
+             const int dst_component,
+             const int src_component,
+             const hier::Box& coarse_box,
+             const hier::IntVector& ratio) const;
+
+  void
+  coarsen_3D(hier::Patch& coarse,
+             const hier::Patch& fine,
+             const int dst_component,
+             const int src_component,
+             const hier::Box& coarse_box,
+             const hier::IntVector& ratio) const;
+
+private:
+  std::string d_name_id;
+
+};
+
+}
+}
+}
+#endif
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/V_Coarsen/coarsen_2D.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/V_Coarsen/coarsen_2D.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,241 @@
+/*************************************************************************
+ *
+ * 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:   Weighted averaging operator for side-centered double data on
+ *                a Cartesian mesh. 
+ *
+ ************************************************************************/
+
+#include "Elastic/V_Coarsen.h"
+
+#include <float.h>
+#include <math.h>
+#include "SAMRAI/geom/CartesianPatchGeometry.h"
+#include "SAMRAI/hier/Index.h"
+#include "SAMRAI/pdat/SideData.h"
+#include "SAMRAI/pdat/SideVariable.h"
+#include "SAMRAI/tbox/Utilities.h"
+#include "Constants.h"
+
+#include "FTensor.hpp"
+
+using namespace SAMRAI;
+
+inline void coarsen_point_2D(const pdat::SideIndex &coarse,
+                             const hier::Index &ip, const hier::Index &jp,
+                             tbox::Pointer<pdat::SideData<double> > &v,
+                             tbox::Pointer<pdat::SideData<double> > &v_fine )
+{
+  pdat::SideIndex center(coarse*2);
+  (*v)(coarse)=((*v_fine)(center) + (*v_fine)(center+jp))/4
+    + ((*v_fine)(center-ip) + (*v_fine)(center-ip+jp)
+       + (*v_fine)(center+ip) + (*v_fine)(center+jp+ip))/8;
+}
+
+
+void SAMRAI::geom::Elastic::V_Coarsen::coarsen_2D
+(hier::Patch& coarse,
+ const hier::Patch& fine,
+ const int dst_component,
+ const int src_component,
+ const hier::Box& coarse_box,
+ const hier::IntVector& ratio) const
+{
+  const tbox::Dimension& Dim(getDim());
+
+  TBOX_DIM_ASSERT_CHECK_DIM_ARGS4(Dim, coarse, fine, coarse_box, ratio);
+
+  tbox::Pointer<pdat::SideData<double> >
+    v_fine = fine.getPatchData(src_component);
+  tbox::Pointer<pdat::SideData<double> >
+    v = coarse.getPatchData(dst_component);
+
+  TBOX_ASSERT(!v.isNull());
+  TBOX_ASSERT(!v_fine.isNull());
+  TBOX_ASSERT(v_fine->getDepth() == v->getDepth());
+  TBOX_ASSERT(v->getDepth() == 1);
+
+  const hier::IntVector& directions(v->getDirectionVector());
+
+  TBOX_ASSERT(directions ==
+              hier::IntVector::min(directions, v_fine->getDirectionVector()));
+
+  const tbox::Pointer<CartesianPatchGeometry> cgeom =
+    coarse.getPatchGeometry();
+  const double *dx=cgeom->getDx();
+
+  /* Numbering of v nodes is
+
+     x--x--x--x--x  Fine
+     0  1  2  3  4
+
+     x-----x-----x Coarse
+     0     1     2
+
+     So the i'th coarse point is affected by the i*2-1,
+     i*2, and i*2+1 fine points.  So, for example, i_fine=3
+     affects both i_coarse=1 and i_coarse=2.
+
+     |---------------------------------------------------------------|
+     |               |               |               |               |
+     f       f       f       f       f       f       f       f       f
+     |               |               |               |               |
+     c               c               c               c               c
+     |               |               |               |               |
+     f       f       f       f       f       f       f       f       f
+     |               |               |               |               |
+     |---------------------------------------------------------------|
+     |               |               |               |               |
+     f       f       f       f       f       f       f       f       f
+     |               |               |               |               |
+     c               c               c               c               c
+     |               |               |               |               |
+     f       f       f       f       f       f       f       f       f
+     |               |               |               |               |
+     |---------------------------------------------------------------|
+
+     In 2D, a coarse point depends on six points.  In this
+     case, (i*2,j*2), (i*2,j*2+1), (i*2-1,j*2),
+     (i*2-1,j*2+1), (i*2+1,j*2), (i*2+1,j*2+1).
+
+     The coarse/fine boundaries get fixed up later in
+     V_Coarsen_Patch_Strategy::postprocessCoarsen.
+  */
+  hier::Index ip(1,0), jp(0,1);
+  for(int j=coarse_box.lower(1); j<=coarse_box.upper(1)+1; ++j)
+    for(int i=coarse_box.lower(0); i<=coarse_box.upper(0)+1; ++i)
+      {
+        if(directions(0) && j!=coarse_box.upper(1)+1)
+          {
+            pdat::SideIndex coarse(hier::Index(i,j),0,
+                                   pdat::SideIndex::Lower);
+            pdat::SideIndex fine(coarse*2);
+            if((i==coarse_box.lower(0)
+                && cgeom->getTouchesRegularBoundary(0,0))
+               || (i==coarse_box.upper(0)+1
+                   && cgeom->getTouchesRegularBoundary(0,1)))
+              {
+                (*v)(coarse)=((*v_fine)(fine) + (*v_fine)(fine+jp))/2;
+              }
+            else
+              {
+                const int axis=0;
+                FTensor::Tensor1<double,3> offset(0,0,0);
+                offset(axis)=dx[axis]/2;
+                FTensor::Tensor1<double,3> xyz(0,0,0);
+                for(int d=0;d<Dim.getValue();++d)
+                  xyz(d)=cgeom->getXLower()[d]
+                    + dx[d]*(coarse[d]-coarse_box.lower()[d] + 0.5) - offset(d);
+
+                coarsen_point_2D(coarse,ip,jp,v,v_fine);
+
+
+                // tbox::pout << "coarsen "
+                //            << coarse << " "
+                //            << xyz(0) << " "
+                //            << xyz(1) << " "
+                //            << dx[0] << " "
+                //            << fine << " "
+                //            << (*v)(coarse) << " "
+                //            << (*v_fine)(fine) << " "
+                //            << (*v_fine)(fine+ip) << " "
+                //            << (*v_fine)(fine-ip) << " "
+                //            << (*v_fine)(fine+jp) << " "
+                //            << (*v_fine)(fine+jp+ip) << " "
+                //            << (*v_fine)(fine+jp-ip) << " "
+                //            << "\n";
+              }
+          }
+        if(directions(1) && i!=coarse_box.upper(0)+1)
+          {
+            pdat::SideIndex coarse(hier::Index(i,j),1,
+                                   pdat::SideIndex::Lower);
+            pdat::SideIndex fine(coarse*2);
+            if((j==coarse_box.lower(1)
+                && cgeom->getTouchesRegularBoundary(1,0))
+               || (j==coarse_box.upper(1)+1
+                   && cgeom->getTouchesRegularBoundary(1,1)))
+              {
+                (*v)(coarse)=((*v_fine)(fine) + (*v_fine)(fine+ip))/2;
+              }
+            else
+              {
+                const int axis=1;
+                FTensor::Tensor1<double,3> offset(0,0,0);
+                offset(axis)=dx[axis]/2;
+                FTensor::Tensor1<double,3> xyz(0,0,0);
+                for(int d=0;d<Dim.getValue();++d)
+                  xyz(d)=cgeom->getXLower()[d]
+                    + dx[d]*(coarse[d]-coarse_box.lower()[d] + 0.5) - offset(d);
+
+                if(xyz(0)-dx[0]<0.5 && xyz(0)+dx[0]>0.5)
+                  {
+                    /* Interface between coarse and fine+1 */
+                    if((xyz(1)+dx[1]/2>0.6 && xyz(1)<0.6)
+                       || (xyz(1)+dx[1]/2>0.4 && xyz(1)<0.4))
+                      {
+                        // tbox::pout << "coarsen m ";
+                        (*v)(coarse)=(((*v_fine)(fine) + (*v_fine)(fine+ip))*2
+                                      + (*v_fine)(fine-jp) + (*v_fine)(fine+ip-jp))/3;
+                      }
+                    /* Interface between coarse and fine-1 */
+                    else if((xyz(1)-dx[1]/2<0.6 && xyz(1)>0.6)
+                            || (xyz(1)-dx[1]/2<0.4 && xyz(1)>0.4))
+                      {
+                        // tbox::pout << "coarsen p ";
+                        (*v)(coarse)=(((*v_fine)(fine) + (*v_fine)(fine+ip))*2
+                                      + (*v_fine)(fine+jp) + (*v_fine)(fine+ip+jp))/3;
+                      }
+                    else
+                      {
+                        // tbox::pout << "coarsen z ";
+                        coarsen_point_2D(coarse,jp,ip,v,v_fine);
+                      }
+                  }
+                else
+                  {
+                    // tbox::pout << "coarsen   ";
+                    coarsen_point_2D(coarse,jp,ip,v,v_fine);
+                  }
+
+                // /* Interface between coarse and fine-1 */
+                // if(xyz(0)+dx[0]/4>0.5 && xyz(0)<0.5)
+                //   {
+                //     tbox::pout << "coarsen m ";
+                //     (*v)(coarse)=(*v_fine)(fine)/2
+                //       + ((*v_fine)(fine-jp) + (*v_fine)(fine+jp))/4;
+                //   }
+                // /* Interface between coarse and fine+1 */
+                // else if(xyz(0)-dx[0]/4<0.5 && xyz(0)>0.5)
+                //   {
+                //     tbox::pout << "coarsen p ";
+                //     (*v)(coarse)=(*v_fine)(fine+ip)/2
+                //       + ((*v_fine)(fine-jp+ip) + (*v_fine)(fine+jp+ip))/4;
+                //   }
+                // else
+                //   {
+                //     tbox::pout << "coarsen   ";
+                //     coarsen_point_2D(coarse,jp,ip,v,v_fine);
+                //   }
+
+                // tbox::pout << coarse << " "
+                //            << xyz(0) << " "
+                //            << xyz(1) << " "
+                //            << dx[0] << " "
+                //            << fine << " "
+                //            << (*v)(coarse) << " "
+                //            << (*v_fine)(fine) << " "
+                //            << (*v_fine)(fine+jp) << " "
+                //            << (*v_fine)(fine-jp) << " "
+                //            << (*v_fine)(fine+ip) << " "
+                //            << (*v_fine)(fine+ip+jp) << " "
+                //            << (*v_fine)(fine+ip-jp) << " "
+                //            << "\n";
+              }
+          }
+      }
+}
+
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/V_Coarsen/coarsen_3D.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/V_Coarsen/coarsen_3D.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,200 @@
+/*************************************************************************
+ *
+ * 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:   Weighted averaging operator for side-centered double data on
+ *                a Cartesian mesh. 
+ *
+ ************************************************************************/
+
+#ifndef included_geom_V_Coarsen_C
+#define included_geom_V_Coarsen_C
+
+#include "Elastic/V_Coarsen.h"
+
+#include <float.h>
+#include <math.h>
+#include "SAMRAI/geom/CartesianPatchGeometry.h"
+#include "SAMRAI/hier/Index.h"
+#include "SAMRAI/pdat/SideData.h"
+#include "SAMRAI/pdat/SideVariable.h"
+#include "SAMRAI/tbox/Utilities.h"
+#include "Constants.h"
+
+using namespace SAMRAI;
+
+inline void coarsen_point_3D(const pdat::SideIndex &coarse,
+                             const hier::Index &ip, const hier::Index &jp,
+                             const hier::Index &kp,
+                             tbox::Pointer<pdat::SideData<double> > &v,
+                             tbox::Pointer<pdat::SideData<double> > &v_fine )
+{
+  pdat::SideIndex center(coarse*2);
+  (*v)(coarse)=((*v_fine)(center) + (*v_fine)(center+jp)
+                + (*v_fine)(center+kp) + (*v_fine)(center+jp+kp))/8
+    + ((*v_fine)(center-ip) + (*v_fine)(center-ip+jp)
+       + (*v_fine)(center-ip+kp) + (*v_fine)(center-ip+jp+kp)
+       + (*v_fine)(center+ip) + (*v_fine)(center+jp+ip)
+       + (*v_fine)(center+ip+kp) + (*v_fine)(center+jp+ip+kp))/16;
+}
+
+
+void SAMRAI::geom::Elastic::V_Coarsen::coarsen_3D
+(hier::Patch& coarse,
+ const hier::Patch& fine,
+ const int dst_component,
+ const int src_component,
+ const hier::Box& coarse_box,
+ const hier::IntVector& ratio) const
+{
+  const tbox::Dimension& dim(getDim());
+
+  TBOX_DIM_ASSERT_CHECK_DIM_ARGS4(dim, coarse, fine, coarse_box, ratio);
+
+  tbox::Pointer<pdat::SideData<double> >
+    v_fine = fine.getPatchData(src_component);
+  tbox::Pointer<pdat::SideData<double> >
+    v = coarse.getPatchData(dst_component);
+
+  TBOX_ASSERT(!v.isNull());
+  TBOX_ASSERT(!v_fine.isNull());
+  TBOX_ASSERT(v_fine->getDepth() == v->getDepth());
+  TBOX_ASSERT(v->getDepth() == 1);
+
+  const hier::IntVector& directions(v->getDirectionVector());
+
+  TBOX_ASSERT(directions ==
+              hier::IntVector::min(directions, v_fine->getDirectionVector()));
+
+  const tbox::Pointer<CartesianPatchGeometry> cgeom =
+    coarse.getPatchGeometry();
+
+  /* Numbering of v nodes is
+
+     x--x--x--x--x  Fine
+     0  1  2  3  4
+
+     x-----x-----x Coarse
+     0     1     2
+
+     So the i'th coarse point is affected by the i*2-1,
+     i*2, and i*2+1 fine points.  So, for example, i_fine=3
+     affects both i_coarse=1 and i_coarse=2.
+
+     |---------------------------------------------------------------|
+     |               |               |               |               |
+     f       f       f       f       f       f       f       f       f
+     |               |               |               |               |
+     c               c               c               c               c
+     |               |               |               |               |
+     f       f       f       f       f       f       f       f       f
+     |               |               |               |               |
+     |---------------------------------------------------------------|
+     |               |               |               |               |
+     f       f       f       f       f       f       f       f       f
+     |               |               |               |               |
+     c               c               c               c               c
+     |               |               |               |               |
+     f       f       f       f       f       f       f       f       f
+     |               |               |               |               |
+     |---------------------------------------------------------------|
+
+     In 2D, a coarse point depends on six points.  In this
+     case, (i*2,j*2), (i*2,j*2+1), (i*2-1,j*2),
+     (i*2-1,j*2+1), (i*2+1,j*2), (i*2+1,j*2+1).
+
+
+          --------------------
+         /                   /|
+        /                   / |
+       /                   /  |
+      /                   /   |
+      -------------------     |
+     |                   |    |
+     |    f        f     |    |
+     |                   |    |
+     |        C          |   /
+     |                   |  /
+     |    f        f     | /
+     |                   |/
+      -------------------
+
+     In 3D, a coarse point depend on 12 points
+     (i*2,j*2,k*2), (i*2,j*2+1,k*2), (i*2,j*2,k*2+1), (i*2,j*2+1,k*2+1),
+     (i*2+1,j*2,k*2), (i*2+1,j*2+1,k*2), (i*2+1,j*2,k*2+1), (i*2+1,j*2+1,k*2+1),
+     (i*2-1,j*2,k*2), (i*2-1,j*2+1,k*2), (i*2-1,j*2,k*2+1), (i*2-1,j*2+1,k*2+1)
+
+     The coarse/fine boundaries get fixed up later in
+     V_Coarsen_Patch_Strategy::postprocessCoarsen.
+  */
+  hier::Index ip(1,0,0), jp(0,1,0), kp(0,0,1);
+  for(int k=coarse_box.lower(2); k<=coarse_box.upper(2)+1; ++k)
+    for(int j=coarse_box.lower(1); j<=coarse_box.upper(1)+1; ++j)
+      for(int i=coarse_box.lower(0); i<=coarse_box.upper(0)+1; ++i)
+        {
+          if(directions(0) && j!=coarse_box.upper(1)+1
+              && k!=coarse_box.upper(2)+1)
+            {
+              pdat::SideIndex coarse(hier::Index(i,j,k),0,
+                                     pdat::SideIndex::Lower);
+              pdat::SideIndex center(coarse*2);
+              if((i==coarse_box.lower(0)
+                  && cgeom->getTouchesRegularBoundary(0,0))
+                 || (i==coarse_box.upper(0)+1
+                     && cgeom->getTouchesRegularBoundary(0,1)))
+                {
+                  (*v)(coarse)=
+                    ((*v_fine)(center) + (*v_fine)(center+jp)
+                     + (*v_fine)(center+kp) + (*v_fine)(center+jp+kp))/4;
+                }
+              else
+                {
+                  coarsen_point_3D(coarse,ip,jp,kp,v,v_fine);
+                }
+            }
+          if(directions(1) && i!=coarse_box.upper(0)+1
+             && k!=coarse_box.upper(2)+1)
+            {
+              pdat::SideIndex coarse(hier::Index(i,j,k),1,
+                                     pdat::SideIndex::Lower);
+              pdat::SideIndex center(coarse*2);
+              if((j==coarse_box.lower(1)
+                  && cgeom->getTouchesRegularBoundary(1,0))
+                 || (j==coarse_box.upper(1)+1
+                     && cgeom->getTouchesRegularBoundary(1,1)))
+                {
+                  (*v)(coarse)=
+                    ((*v_fine)(center) + (*v_fine)(center+ip)
+                     + (*v_fine)(center+kp) + (*v_fine)(center+ip+kp))/4;
+                }
+              else
+                {
+                  coarsen_point_3D(coarse,jp,kp,ip,v,v_fine);
+                }
+            }
+          if(directions(2) && i!=coarse_box.upper(0)+1
+              && j!=coarse_box.upper(1)+1)
+            {
+              pdat::SideIndex coarse(hier::Index(i,j,k),2,
+                                     pdat::SideIndex::Lower);
+              pdat::SideIndex center(coarse*2);
+              if((k==coarse_box.lower(2)
+                  && cgeom->getTouchesRegularBoundary(2,0))
+                 || (k==coarse_box.upper(2)+1
+                     && cgeom->getTouchesRegularBoundary(2,1)))
+                {
+                  (*v)(coarse)=
+                    ((*v_fine)(center) + (*v_fine)(center+ip)
+                     + (*v_fine)(center+jp) + (*v_fine)(center+ip+jp))/4;
+                }
+              else
+                {
+                  coarsen_point_3D(coarse,kp,ip,jp,v,v_fine);
+                }
+            }
+        }
+}
+
+#endif
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/V_Coarsen_Patch_Strategy.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/V_Coarsen_Patch_Strategy.h	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,415 @@
+/*************************************************************************
+ *
+ * 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:   Robin boundary condition support on cartesian grids. 
+ *
+ ************************************************************************/
+#ifndef GAMRA_ELASTIC_V_COARSEN_PATCH_STRATEGY_H
+#define GAMRA_ELASTIC_V_COARSEN_PATCH_STRATEGY_H
+
+#include "SAMRAI/SAMRAI_config.h"
+
+#include "SAMRAI/xfer/CoarsenPatchStrategy.h"
+#include "SAMRAI/geom/CartesianPatchGeometry.h"
+#include "SAMRAI/hier/CoarseFineBoundary.h"
+#include "SAMRAI/pdat/SideData.h"
+#include "SAMRAI/pdat/CellIndex.h"
+#include "Constants.h"
+#include "set_boundary.h"
+
+namespace SAMRAI {
+namespace solv {
+namespace Elastic {
+
+/*!
+ * @brief Helper utility for setting boundary conditions on V.
+ *
+ * This class inherits and implements virtual functions from
+ * xfer::CoarsenPatchStrategy so it may be used to help create
+ * communication schedules if desired.
+ */
+class V_Coarsen_Patch_Strategy:
+   public xfer::CoarsenPatchStrategy
+{
+
+public:
+   /*!
+    * @brief Constructor using.
+    *
+    * @param object_name Name of the object, for general referencing.
+    * @param coef_strategy Coefficients strategy being helped.
+    */
+   V_Coarsen_Patch_Strategy(
+      const tbox::Dimension& dim,
+      std::string object_name = std::string()):
+     xfer::CoarsenPatchStrategy(dim),
+     d_object_name(object_name) {}
+
+   /*!
+    * @brief Destructor.
+    */
+   virtual ~V_Coarsen_Patch_Strategy(void) {}
+
+   //@{ @name xfer::CoarsenPatchStrategy virtuals
+
+   virtual hier::IntVector
+   getCoarsenOpStencilWidth() const
+  { return hier::IntVector::getOne(getDim()); }
+
+   virtual void
+   preprocessCoarsen(hier::Patch& ,
+                    const hier::Patch& fine,
+                    const hier::Box& ,
+                    const hier::IntVector& )
+  {
+    set_boundary(fine,invalid_id,v_id,true);
+  }
+
+   virtual void
+   postprocessCoarsen(
+      hier::Patch& coarse,
+      const hier::Patch& fine,
+      const hier::Box& coarse_box,
+      const hier::IntVector& ratio)
+  {
+    if(getDim().getValue()==2)
+      postprocessCoarsen_2D(coarse,fine,coarse_box,ratio);
+    else
+      postprocessCoarsen_3D(coarse,fine,coarse_box,ratio);
+  }
+
+  void
+  postprocessCoarsen_2D(
+      hier::Patch& coarse,
+      const hier::Patch& fine,
+      const hier::Box& coarse_box,
+      const hier::IntVector& ratio);
+
+  void
+  postprocessCoarsen_3D(
+      hier::Patch& coarse,
+      const hier::Patch& fine,
+      const hier::Box& coarse_box,
+      const hier::IntVector& ratio);
+
+   //@}
+
+   //@{
+
+   /*!
+    * @name Functions to set boundary condition values
+    */
+
+   /*!
+    * @brief Set the physical boundary condition by setting the
+    * value of the first ghost cells.
+    *
+    * This function has an interface similar to the virtual function
+    * xfer::CoarsenPatchStrategy::setPhysicalBoundaryConditions(),
+    * and it may be used to help implement that function,
+    * but it does not serve the same purpose.  The primary
+    * differences are:
+    * -# It specializes to cell-centered variables.
+    * -# Only one ghost cell width is filled.  Setting a Robin
+    *    boundary condition for cell-centered quantities requires
+    *    only one ghost cell to be set.
+    *    (More ghost cells can be filled by continuing the linear
+    *    distribution of data beyond the first cell, but that is
+    *    not implemented at this time.)
+    * -# User must specify the index of the data whose ghost
+    *    cells need to be filled.  This index is used to determine
+    *    the variable for which to set the boundary coefficients
+    *    and to get the data to be set.
+    *
+    * This function calls RobinBcStrategy::setBcCoefs() to
+    * get the coefficients, then it sets the values in the first
+    * ghost cell on the boundary.
+    *
+    * To determine the value for the ghost cell,
+    * a @em linear approximation in the direction normal to the
+    * boundary is assumed.  We write the following discrete
+    * approximations:
+    * @f[ u_b = \frac{ u_i + u_o }{2} @f]
+    * @f[ [u_n]_b = \frac{ u_o - u_i }{h} @f]
+    * where the subscript b stands for the the boundary,
+    * i stands for the first cell inside the boundary and
+    * o stands for the first cell outside the boundary
+    * and h is the grid spacing normal to the boundary.
+    * Applying this to the Robin formula gives
+    * @f[ u_o = \frac{ h\gamma + u_i( \beta - \frac{h}{2} \alpha ) }
+    * { \beta + \frac{h}{2} \alpha } @f] or equivalently
+    * @f[ u_o = \frac{ hg + u_i (1-a(1+\frac{h}{2})) }{ 1-a(1-\frac{h}{2}) } @f]
+    *
+    * After setting the edge (face in 3D) boundary conditions,
+    * linear approximations are used to set the boundary conditions
+    * of higher boundary types (nodes in 2D, edges and nodes in 3D).
+    *
+    * In some cases, the calling function wants to set the
+    * boundary condition homogeneously, with g=0.
+    * This is useful in problems where the the solution of the
+    * homogeneous problem is required in solving the inhomogeneous
+    * problem.  This function respects such requests specified
+    * through the argument @c homogeneous_bc.
+    *
+    * @internal To be more general to other data types,
+    * there could be versions for other data types also,
+    * such as ...InNodes, ...InFaces, etc.  However, I'm not
+    * sure exactly how to implement the Robin boundary condition
+    * on the faces and nodes when m != 1.  Should the boundary
+    * value be set or should the first ghost value be set?
+    *
+    * @internal I have not addressed possibility of differences
+    * in chosing the discrete formulation with which to compute
+    * the boundary value.  The above formulation is obviously
+    * one specific approximation, but there could be others.
+    * If anoter approximation is required, there should be
+    * another class like this or this class can offer a choice
+    * to be set by the user.  I favor another class.
+    *
+    * @internal Since the data alignment can be found through
+    * the target_data_id, these types of functions may be changed
+    * to just plain setBoundaryValues or setBoundaryValuesInBoundaryBoxes
+    * since it does assume boundary boxes.  This may have to be
+    * expanded to later include coarse-fine boundary boxes
+    * for more generality.
+    *
+    * @param patch hier::Patch on which to set boundary condition
+    * @param fill_time Solution time corresponding to filling
+    * @param ghost_width_to_fill Max ghost width requiring fill
+    * @param target_data_id hier::Patch data index of data to be set.
+    *        This data must be a cell-centered double.
+    * @param homogeneous_bc Set a homogeneous boundary condition.
+    *    This means g=0 for the boundary.
+    */
+   // void
+   // setBoundaryValuesInCells(
+   //    hier::Patch& patch,
+   //    const double fill_time,
+   //    const hier::IntVector& ghost_width_to_fill,
+   //    int target_data_id,
+   //    bool homogeneous_bc = false) const;
+
+   /*!
+    * @brief Set ghost cells for an entire level.
+    *
+    * Loop through all patches on the given level and call
+    * setBoundaryValuesInCells(hier::Patch &patch,
+    *                          const double fill_time ,
+    *                          const hier::IntVector &ghost_width_to_fill ,
+    *                          int target_data_id ,
+    *                          bool homogeneous_bc=false )
+    * for each.
+    *
+    * @param level PatchLevel on which to set boundary condition
+    * @param fill_time Solution time corresponding to filling
+    * @param ghost_width_to_fill Max ghost width requiring fill
+    * @param target_data_id hier::Patch data index of data to be set.
+    *        This data must be a cell-centered double.
+    * @param homogeneous_bc Set a homogeneous boundary condition.
+    *    This means g=0 for the boundary.
+    */
+   // void
+   // setBoundaryValuesInCells(
+   //    hier::PatchLevel& level,
+   //    const double fill_time,
+   //    const hier::IntVector& ghost_width_to_fill,
+   //    int target_data_id,
+   //    bool homogeneous_bc = false) const;
+
+   /*!
+    * @brief Set the physical boundary condition by setting the
+    * value of the boundary nodes.
+    *
+    * This function is not yet implemented!
+    *
+    * There are some decisions that must be made before
+    * the implementation can be written.
+    * -# Do we set the values on the boundary or one cell
+    *    away from the boundary?
+    * -# What is the discrete formulation we should use
+    *    to compute the value to be set?
+    *
+    * This function has an interface similar to the virtual function
+    * xfer::CoarsenPatchStrategy::setPhysicalBoundaryConditions(),
+    * and it may be used to help implement that function,
+    * but it does not serve the same purpose.  The primary
+    * differences are:
+    * -# It specializes to node-centered variables.
+    * -# User must specify the index of the data whose ghost
+    *    cells need to be filled.  This index is used to determine
+    *    the variable for which to set the boundary coefficients
+    *    and to get the data to be set.
+    *
+    * This function calls RobinBcStrategy::setBcCoefs() to get the
+    * coefficients, then it sets the values at the boundary nodes.
+    *
+    * In some cases, the calling function wants to set the
+    * boundary condition homogeneously, with g=0.
+    * This is useful in problems where the the solution of the
+    * homogeneous problem is required to solving the inhomogeneous
+    * problem.  This function respects such requests specified
+    * through the argument @c homogeneous_bc.
+    *
+    * @param patch hier::Patch on which to set boundary condition
+    * @param fill_time Solution time corresponding to filling
+    * @param target_data_id hier::Patch data index of data to be set.
+    * @param homogeneous_bc Set a homogeneous boundary condition.
+    *    This means g=0 for the boundary.
+    */
+   // void
+   // setBoundaryValuesAtNodes(
+   //    hier::Patch& patch,
+   //    const double fill_time,
+   //    int target_data_id,
+   //    bool homogeneous_bc = false) const;
+
+   //@}
+
+   //@{
+   /*!
+    * @name Ways to provide the Robin bc coefficients
+    */
+
+   /*!
+    * @brief Provide an implementation of the RobinBcCoefStrategy
+    * for determining the boundary coefficients.
+    *
+    * Provide the implementation that can be used to set the
+    * Robin bc coefficients.
+    *
+    * @param coef_strategy tbox::Pointer to a concrete inmplementation of
+    *        the coefficient strategy.
+    */
+   // void
+   // setCoefImplementation(
+   //    const RobinBcCoefStrategy* coef_strategy);
+
+   /*!
+    * @brief Set the data id that should be filled when setting
+    * physical boundary conditions.
+    *
+    * When setPhysicalBoundaryConditions is called, the data
+    * specified will be set.  This information is required because
+    * the it is not passed in through the argument list of
+    * setPhysicalBounaryConditions.
+    */
+  void setSourceDataId(int id)
+  {
+    v_id=id;
+  }
+
+   /*!
+    * @brief Set whether boundary filling should assume homogeneous
+    * conditions.
+    *
+    * In certain circumstances, only the value of a is needed, while
+    * the value of g is temporarily not required and taken to be zero.
+    * (An example is in setting the boundary condition for error
+    * value in an iterative method.)  In such cases, use this function
+    * to set a flag that will cause a null pointer to be given to
+    * setBcCoefs() to indicate that fact.
+    */
+   // void
+   // setHomogeneousBc(
+   //    bool homogeneous_bc);
+
+   //@}
+
+  tbox::Array<tbox::Pointer<hier::CoarseFineBoundary> > coarse_fine;
+
+private:
+   /*!
+    * @brief Trim a boundary box so that it does not stick out
+    * past a given box.
+    *
+    * Certain boundary-related operations occur on patch data that
+    * do not or cannot extend past the edgr or corner of a patch.
+    * This function is used to trim down the parts of the boundary box
+    * that extend past those points so that a suitable index range
+    * is achieved.
+    *
+    * The boundary box trimmed must be of type 1 or 2.
+    *
+    * @param boundary_box Boundary box to be trimmed.
+    * @param limit_box hier::Box to not stick past
+    *
+    * @return New trimmed boundary box.
+    */
+   // hier::BoundaryBox
+   // trimBoundaryBox(
+   //    const hier::BoundaryBox& boundary_box,
+   //    const hier::Box& limit_box) const;
+
+   /*!
+    * @brief Return box describing the index space of boundary nodes
+    * defined by a boundary box.
+    *
+    * Define a box describing the indices of the nodes corresponding
+    * to the input boundary box.  These nodes lie on the boundary
+    * itself.
+    *
+    * The input boundary_box must be of type 1
+    * (see hier::BoundaryBox::getBoundaryType()).
+    *
+    * @param boundary_box input boundary box
+    * @return a box to define the node indices corresponding to
+    *   boundary_box
+    */
+   // hier::Box
+   // makeNodeBoundaryBox(
+   //    const hier::BoundaryBox& boundary_box) const;
+
+   /*!
+    * @brief Return box describing the index space of faces
+    * defined by a boundary box.
+    *
+    * Define a box describing the indices of the codimension 1
+    * surface corresponding to the input boundary box.
+    *
+    * The input boundary_box must be of type 1
+    * (see hier::BoundaryBox::getBoundaryType()).
+    *
+    * This is a utility function for working with the
+    * indices coresponding to a boundary box but coincide
+    * with the patch boundary.
+    *
+    * @param boundary_box input boundary box
+    * @return a box to define the face indices corresponding to
+    *    boundary_box
+    */
+   // hier::Box
+   // makeFaceBoundaryBox(
+   //    const hier::BoundaryBox& boundary_box) const;
+
+   std::string d_object_name;
+
+   /*!
+    * @brief Coefficient strategy giving a way to get to
+    * Robin bc coefficients.
+    */
+   // const RobinBcCoefStrategy* d_coef_strategy;
+
+   /*!
+    * @brief hier::Index of target patch data when filling ghosts.
+    */
+   int v_id;
+
+   /*!
+    * @brief Whether to assumg g=0 when filling ghosts.
+    */
+   // bool d_homogeneous_bc;
+
+   /*!
+    * @brief Timers for performance measurement.
+    */
+   // tbox::Pointer<tbox::Timer> t_set_boundary_values_in_cells;
+   // tbox::Pointer<tbox::Timer> t_use_set_bc_coefs;
+};
+
+}
+}
+}
+#endif  // included_solv_V_Coarsen_Patch_Strategy
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/V_Coarsen_Patch_Strategy/postprocessCoarsen_2D.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/V_Coarsen_Patch_Strategy/postprocessCoarsen_2D.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,89 @@
+#include "Elastic/V_Coarsen_Patch_Strategy.h"
+
+void
+SAMRAI::solv::Elastic::V_Coarsen_Patch_Strategy::postprocessCoarsen_2D
+(hier::Patch& coarse,
+ const hier::Patch& fine,
+ const hier::Box& ,
+ const hier::IntVector& )
+{
+  /* Fix up the boundary elements by iterating through the boundary
+     boxes */
+
+  /* We only care about edges, not corners, so we only iterate over
+     edge boundary boxes. */
+  const tbox::Array<hier::BoundaryBox>
+    &boundaries=coarse_fine[fine.getPatchLevelNumber()]->getEdgeBoundaries(coarse.getGlobalId());
+     
+  tbox::Pointer<pdat::SideData<double> >
+    v_fine = fine.getPatchData(v_id);
+  tbox::Pointer<pdat::SideData<double> >
+    v = coarse.getPatchData(v_id);
+
+  TBOX_ASSERT(!v.isNull());
+  TBOX_ASSERT(!v_fine.isNull());
+  TBOX_ASSERT(v_fine->getDepth() == v->getDepth());
+  TBOX_ASSERT(v->getDepth() == 1);
+
+  hier::Box gbox(v_fine->getGhostBox());
+  hier::Index ip(1,0), jp(0,1);
+  for(int mm=0; mm<boundaries.size(); ++mm)
+    {
+      hier::Box bbox=boundaries[mm].getBox();
+      int location_index=boundaries[mm].getLocationIndex();
+
+      hier::Index lower=hier::Index::coarsen(bbox.lower(),hier::Index(2,2)),
+        upper=hier::Index::coarsen(bbox.upper(),hier::Index(2,2));
+
+      for(int j=lower(1); j<=upper(1); ++j)
+        for(int i=lower(0); i<=upper(0); ++i)
+          {
+            /* Fix vx */
+            if(location_index==0)
+              {
+                pdat::SideIndex coarse(hier::Index(i,j),0,
+                                       pdat::SideIndex::Upper);
+                pdat::SideIndex center(coarse*2);
+                if(center[1]>=gbox.lower(1) && center[1]<gbox.upper(1))
+                  {
+                    (*v)(coarse)=((*v_fine)(center) + (*v_fine)(center+jp))/2;
+                  }
+              }
+            else if(location_index==1)
+              {
+                pdat::SideIndex coarse(hier::Index(i,j),0,
+                                       pdat::SideIndex::Lower);
+                pdat::SideIndex center(coarse*2);
+                if(center[1]>=gbox.lower(1) && center[1]<gbox.upper(1))
+                  {
+                    (*v)(coarse)=((*v_fine)(center) + (*v_fine)(center+jp))/2;
+                  }
+              }
+            /* Fix vy */
+            else if(location_index==2)
+              {
+                pdat::SideIndex coarse(hier::Index(i,j),1,
+                                       pdat::SideIndex::Upper);
+                pdat::SideIndex center(coarse*2);
+                if(center[0]>=gbox.lower(0) && center[0]<gbox.upper(0))
+                  {
+                    (*v)(coarse)=((*v_fine)(center) + (*v_fine)(center+ip))/2;
+                  }
+              }
+            else if(location_index==3)
+              {
+                pdat::SideIndex coarse(hier::Index(i,j),1,
+                                       pdat::SideIndex::Lower);
+                pdat::SideIndex center(coarse*2);
+                if(center[0]>=gbox.lower(0) && center[0]<gbox.upper(0))
+                  {
+                    (*v)(coarse)=((*v_fine)(center) + (*v_fine)(center+ip))/2;
+                  }
+              }
+            else
+              {
+                abort();
+              }
+          }
+    }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/V_Coarsen_Patch_Strategy/postprocessCoarsen_3D.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/V_Coarsen_Patch_Strategy/postprocessCoarsen_3D.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,87 @@
+#include "Elastic/V_Coarsen_Patch_Strategy.h"
+
+void
+SAMRAI::solv::Elastic::V_Coarsen_Patch_Strategy::postprocessCoarsen_3D
+(hier::Patch& coarse,
+ const hier::Patch& fine,
+ const hier::Box& ,
+ const hier::IntVector& )
+{
+  /* Fix up the boundary elements by iterating through the boundary
+     boxes */
+
+  /* We only care about faces, not edges or corners, so we only
+     iterate over face boundary boxes. */
+  const tbox::Array<hier::BoundaryBox> &boundaries
+    (coarse_fine[fine.getPatchLevelNumber()]
+     ->getFaceBoundaries(coarse.getGlobalId()));
+     
+  tbox::Pointer<pdat::SideData<double> >
+    v_fine = fine.getPatchData(v_id);
+  tbox::Pointer<pdat::SideData<double> >
+    v = coarse.getPatchData(v_id);
+
+  TBOX_ASSERT(!v.isNull());
+  TBOX_ASSERT(!v_fine.isNull());
+  TBOX_ASSERT(v_fine->getDepth() == v->getDepth());
+  TBOX_ASSERT(v->getDepth() == 1);
+
+  hier::Box gbox(v_fine->getGhostBox());
+  hier::Index ip(1,0,0), jp(0,1,0), kp(0,0,1);
+  for(int mm=0; mm<boundaries.size(); ++mm)
+    {
+      hier::Box bbox=boundaries[mm].getBox();
+      /* location_index tells where, in relation to the box, the boundary is.
+         0: x lower
+         1: x upper
+         2: y lower
+         3: y upper
+         4: z lower
+         5: z upper
+
+         Therefore, if location_index==3, then we need to set vy on
+         the __lower__ side of that boundary box. */
+         
+      int location_index=boundaries[mm].getLocationIndex();
+      int direction(location_index/2);
+      int side(location_index%2==0 ? pdat::SideIndex::Upper
+               : pdat::SideIndex::Lower);
+      int dir2((direction+1)%3), dir3((direction+2)%3);
+      hier::Index yp(ip), zp(ip);
+      switch(direction)
+        {
+        case 0:
+          yp=jp;
+          zp=kp;
+          break;
+        case 1:
+          yp=kp;
+          zp=ip;
+          break;
+        case 2:
+          yp=ip;
+          zp=jp;
+          break;
+        }      
+
+      hier::Index lower=hier::Index::coarsen(bbox.lower(),hier::Index(2,2,2)),
+        upper=hier::Index::coarsen(bbox.upper(),hier::Index(2,2,2));
+
+      for(int k=lower(2); k<=upper(2); ++k)
+        for(int j=lower(1); j<=upper(1); ++j)
+          for(int i=lower(0); i<=upper(0); ++i)
+            {
+              pdat::SideIndex coarse(hier::Index(i,j,k),direction,side);
+              pdat::SideIndex center(coarse*2);
+              if(center[dir2]>=gbox.lower(dir2)
+                 && center[dir2]<gbox.upper(dir2)
+                 && center[dir3]>=gbox.lower(dir3)
+                 && center[dir3]<gbox.upper(dir3))
+                {
+                  (*v)(coarse)=
+                    ((*v_fine)(center) + (*v_fine)(center+yp)
+                     + (*v_fine)(center+zp) + (*v_fine)(center+yp+zp))/4;
+                }
+            }
+    }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/V_Refine.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/V_Refine.h	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,158 @@
+/*************************************************************************
+ *
+ * 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:   Linear refine operator for side-centered double data on
+ *                a Cartesian mesh. 
+ *
+ ************************************************************************/
+
+#ifndef GAMRA_ELASTIC_V_REFINE_H
+#define GAMRA_ELASTIC_V_REFINE_H
+
+#include "SAMRAI/SAMRAI_config.h"
+
+#include "SAMRAI/xfer/RefineOperator.h"
+#include "SAMRAI/hier/Box.h"
+#include "SAMRAI/hier/IntVector.h"
+#include "SAMRAI/hier/Patch.h"
+#include "SAMRAI/tbox/Pointer.h"
+#include "SAMRAI/pdat/SideVariable.h"
+#include "SAMRAI/geom/CartesianPatchGeometry.h"
+
+#include "FTensor.hpp"
+#include <string>
+
+namespace SAMRAI {
+namespace geom {
+namespace Elastic {
+
+/**
+ * Class V_Refine implements linear
+ * interpolation for side-centered double patch data defined over a Cartesian
+ * mesh.  It is derived from the xfer::RefineOperator base class.
+ * CartesianSideDoubleConservativeLinearRefine does not handle the 
+ * boundary for the velocity correctly, so use this instead for
+ * velocity.
+ *
+ * The findRefineOperator() operator function returns true if the input
+ * variable is side-centered double, and the std::string is "V_REFINE".
+ *
+ * @see xfer::RefineOperator
+ */
+
+class V_Refine:
+  public xfer::RefineOperator
+{
+public:
+  /**
+   * Uninteresting default constructor.
+   */
+  explicit V_Refine(const tbox::Dimension& dim):
+    xfer::RefineOperator(dim, "V_REFINE")
+  {
+    d_name_id = "V_REFINE";
+  }
+
+
+  /**
+   * Uninteresting virtual destructor.
+   */
+  virtual ~V_Refine(){}
+
+  /**
+   * Return true if the variable and name std::string match side-centered
+   * double linear interpolation; otherwise, return false.
+   */
+  bool findRefineOperator(const tbox::Pointer<hier::Variable>& var,
+                          const std::string& op_name) const
+  {
+    TBOX_DIM_ASSERT_CHECK_ARGS2(*this, *var);
+
+    const tbox::Pointer<pdat::SideVariable<double> > cast_var(var);
+    if (!cast_var.isNull() && (op_name == d_name_id)) {
+      return true;
+    } else {
+      return false;
+    }
+  }
+  /**
+   * Return name std::string identifier of this refinement operator.
+   */
+  const std::string& getOperatorName() const
+  {
+    return d_name_id;
+  }
+
+  /**
+   * The priority of side-centered double linear interpolation is 0.
+   * It will be performed before any user-defined interpolation operations.
+   */
+  int getOperatorPriority() const
+  {
+    return 0;
+  }
+
+  /**
+   * The stencil width of the linear interpolation operator is the vector
+   * of ones.  That is, its stencil extends one side outside the fine box.
+   */
+  hier::IntVector getStencilWidth() const
+  {
+    return hier::IntVector::getOne(getDim());
+  }
+
+  /**
+   * Refine the source component on the coarse patch to the destination
+   * component on the fine patch using the side-centered double linear
+   * interpolation operator.  Interpolation is performed on the intersection
+   * of the destination patch and the boxes contained in fine_overlap
+   * It is assumed that the coarse patch contains sufficient data for the
+   * stencil width of the refinement operator.
+   */
+  void refine(hier::Patch& fine,
+              const hier::Patch& coarse,
+              const int dst_component,
+              const int src_component,
+              const hier::BoxOverlap& fine_overlap,
+              const hier::IntVector& ratio) const;
+
+  /**
+   * Refine the source component on the coarse patch to the destination
+   * component on the fine patch using the side-centered double linear
+   * interpolation operator.  Interpolation is performed on the intersection
+   * of the destination patch and the fine box.   It is assumed that the
+   * coarse patch contains sufficient data for the stencil width of the
+   * refinement operator.  This differs from the above refine() method
+   * only in that it operates on a single fine box instead of a BoxOverlap.
+   */
+  void refine(hier::Patch& fine,
+              const hier::Patch& coarse,
+              const int dst_component,
+              const int src_component,
+              const hier::Box& fine_box,
+              const hier::IntVector& ratio,
+              const int &axis) const;
+
+  double refine_along_line(pdat::SideData<double> &v,
+                           const int &axis,
+                           const int &dim,
+                           const hier::Index pp[],
+                           const pdat::SideIndex &fine,
+                           const pdat::SideIndex &coarse,
+                           const hier::Box &coarse_box,
+                           const CartesianPatchGeometry &coarse_geom,
+                           const FTensor::Tensor1<double,3> &xyz,
+                           const double *dx) const;
+
+private:
+  std::string d_name_id;
+
+};
+
+}
+}
+}
+#endif
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/V_Refine/refine.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/V_Refine/refine.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,127 @@
+/*************************************************************************
+ *
+ * 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:   Linear refine operator for side-centered double data on
+ *                a Cartesian mesh. 
+ *
+ ************************************************************************/
+
+#include "Elastic/V_Refine.h"
+
+#include <float.h>
+#include <math.h>
+#include "SAMRAI/geom/CartesianPatchGeometry.h"
+#include "SAMRAI/hier/Index.h"
+#include "SAMRAI/pdat/SideData.h"
+#include "SAMRAI/pdat/SideVariable.h"
+#include "SAMRAI/tbox/Utilities.h"
+#include "SAMRAI/pdat/CellData.h"
+
+#include "FTensor.hpp"
+
+void SAMRAI::geom::Elastic::V_Refine::refine(
+   hier::Patch& fine,
+   const hier::Patch& coarse,
+   const int dst_component,
+   const int src_component,
+   const hier::BoxOverlap& fine_overlap,
+   const hier::IntVector& ratio) const
+{
+   const pdat::SideOverlap* t_overlap =
+      dynamic_cast<const pdat::SideOverlap *>(&fine_overlap);
+
+   TBOX_ASSERT(t_overlap != NULL);
+
+   for(int axis=0; axis<getDim().getValue(); ++axis)
+     {
+       const hier::BoxList& boxes = t_overlap->getDestinationBoxList(axis);
+       for (hier::BoxList::Iterator b(boxes); b; b++)
+         {
+           refine(fine,coarse,dst_component,src_component,b(),ratio,axis);
+         }
+     }
+}
+
+void SAMRAI::geom::Elastic::V_Refine::refine
+(hier::Patch& fine_patch,
+ const hier::Patch& coarse_patch,
+ const int dst_component,
+ const int src_component,
+ const hier::Box& fine_box,
+ const hier::IntVector& ratio,
+ const int &axis) const
+{
+   const tbox::Dimension& dimension(getDim());
+   const int dim(dimension.getValue());
+   TBOX_DIM_ASSERT_CHECK_DIM_ARGS4(dimension, fine_patch, coarse_patch, fine_box, ratio);
+
+   tbox::Pointer<pdat::SideData<double> >
+   v_ptr = coarse_patch.getPatchData(src_component);
+   pdat::SideData<double> &v(*v_ptr);
+   tbox::Pointer<pdat::SideData<double> >
+   v_fine_ptr = fine_patch.getPatchData(dst_component);
+   pdat::SideData<double> &v_fine(*v_fine_ptr);
+
+#ifdef DEBUG_CHECK_ASSERTIONS
+   TBOX_ASSERT(!v_ptr.isNull());
+   TBOX_ASSERT(!v_fine_ptr.isNull());
+   TBOX_ASSERT(v.getDepth() == v_fine.getDepth());
+   TBOX_ASSERT(v.getDepth() == 1);
+#endif
+
+   hier::Box coarse_box=coarse_patch.getBox();
+   tbox::Pointer<geom::CartesianPatchGeometry>
+     coarse_geom = coarse_patch.getPatchGeometry();
+
+   tbox::Pointer<geom::CartesianPatchGeometry>
+     fine_geom = fine_patch.getPatchGeometry();
+   const double *dx=fine_geom->getDx();
+
+   const hier::Box &fine_patch_box(fine_patch.getBox());
+
+   hier::Index ip(hier::Index::getZeroIndex(dimension)), jp(ip), kp(ip);
+   ip[0]=1;
+   jp[1]=1;
+   if(dim>2)
+     kp[2]=1;
+   hier::Index pp[]={ip,jp,kp};
+
+   for(pdat::CellIterator ci(fine_box); ci; ci++)
+     {
+       pdat::SideIndex fine(*ci,axis,pdat::SideIndex::Lower);
+
+       pdat::SideIndex coarse(fine);
+       coarse.coarsen(hier::Index::getOneIndex(dimension)*2);
+
+       FTensor::Tensor1<double,3> offset(0,0,0);
+       offset(axis)=dx[axis]/2;
+       FTensor::Tensor1<double,3> xyz(0,0,0);
+       for(int d=0;d<dim;++d)
+         xyz(d)=fine_geom->getXLower()[d]
+           + dx[d]*(fine[d]-fine_patch_box.lower()[d] + 0.5) - offset(d);
+
+       if(fine[axis]%2==0)
+         {
+           v_fine(fine)=
+             refine_along_line(v,axis,dim,pp,fine,coarse,coarse_box,
+                               *coarse_geom,xyz,dx);
+         }
+       else
+         {
+           FTensor::Tensor1<double,3> xyz_low, xyz_high;
+           FTensor::Index<'a',3> a;
+
+           xyz_low(a)=xyz(a) - 2*offset(a);
+           xyz_high(a)=xyz(a) + 2*offset(a);
+
+           v_fine(fine)=
+             (refine_along_line(v,axis,dim,pp,fine,coarse,coarse_box,
+                                *coarse_geom,xyz_low,dx)
+              + refine_along_line(v,axis,dim,pp,fine,coarse+pp[axis],
+                                  coarse_box,*coarse_geom,xyz_high,dx))/2;
+         }
+     }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/V_Refine/refine_along_line.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/V_Refine/refine_along_line.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,280 @@
+#include "Elastic/V_Refine.h"
+
+/* This assumes that the levels are always properly nested, so that we
+   always have an extra grid space for interpolation.  So we only have
+   to have a special case for physical boundaries, where we do not
+   have an extra grid space. */
+
+/* Maybe this has to be fixed when dvx/dy != 0 on the outer boundary
+   because the approximation to the derivative is not accurate
+   enough? */
+
+/* Maybe in 3D we should include cross derivatives? */
+
+double SAMRAI::geom::Elastic::V_Refine::refine_along_line
+(pdat::SideData<double> &v,
+ const int &axis,
+ const int &dim,
+ const hier::Index pp[],
+ const pdat::SideIndex &fine,
+ const pdat::SideIndex &coarse,
+ const hier::Box &coarse_box,
+ const CartesianPatchGeometry &coarse_geom,
+ const FTensor::Tensor1<double,3> &xyz,
+ const double *dx) const
+{
+  double result=v(coarse);
+
+  for(int d=(axis+1)%dim;d!=axis;d=(d+1)%dim)
+    {
+      const int sgn(fine[d]%2==0 ? -1 : 1);
+
+      double dvx_dy;
+      if(coarse[d]==coarse_box.lower(d)
+         && coarse_geom.getTouchesRegularBoundary(d,0))
+        {
+          dvx_dy=sgn*(v(coarse+pp[d])-v(coarse))/4;
+        }
+      else if(coarse[d]==coarse_box.upper(d)
+              && coarse_geom.getTouchesRegularBoundary(d,1))
+        {
+          dvx_dy=sgn*(v(coarse)-v(coarse-pp[d]))/4;
+        }
+      else
+        {
+          dvx_dy=sgn*(v(coarse+pp[d])-v(coarse-pp[d]))/8;
+
+          if(axis==0 && xyz(0)-dx[0]<0.5+1e-6 && xyz(0)+dx[0]>0.5+1e-6)
+            {
+              const double y_min(0.5-sgn*0.1), y_max(0.5+sgn*0.1);
+              /* Top tip */
+              /* Singularity in coarse+1 */
+              if(sgn*(xyz(1)+sgn*dx[1]*0.5-y_max)<0 && sgn*(xyz(1)+sgn*dx[1]*2.5-y_max)>0)
+                {
+                  dvx_dy=(v(coarse)-v(coarse-pp[d]*sgn))/4;
+                  // tbox::pout << "refine p cp1 "
+                  //            << 1/dx[0] << " "
+                  //            << xyz(0) << " "
+                  //            << xyz(1) << " "
+                  //            << fine << " "
+                  //            << coarse << " "
+                  //            << sgn << " "
+                  //            << v(coarse+pp[d]*sgn) << " "
+                  //            << v(coarse) << " "
+                  //            << v(coarse-pp[d]*sgn) << " "
+                  //            << result + dvx_dy << " "
+                  //            << "\n";
+
+                }
+              /* Singularity in coarse */
+              else if(sgn*(xyz(1)-sgn*dx[1]*1.5-y_max)<0 && sgn*(xyz(1)+sgn*dx[1]*0.5-y_max)>0)
+                {
+                  dvx_dy=0;
+                  // tbox::pout << "refine p c "
+                  //            << 1/dx[0] << " "
+                  //            << xyz(0) << " "
+                  //            << xyz(1) << " "
+                  //            << fine << " "
+                  //            << coarse << " "
+                  //            << sgn << " "
+                  //            << v(coarse+pp[d]*sgn) << " "
+                  //            << v(coarse) << " "
+                  //            << v(coarse-pp[d]*sgn) << " "
+                  //            << result + dvx_dy << " "
+                  //            << "\n";
+                }
+              /* Singularity in coarse-1 */
+              else if(sgn*(xyz(1)-sgn*dx[1]*3.5-y_max)<0 && sgn*(xyz(1)-sgn*dx[1]*1.5-y_max)>0)
+                {
+                  dvx_dy=(v(coarse+pp[d]*sgn)-v(coarse))/4;
+                  // tbox::pout << "refine p cm1 "
+                  //            << 1/dx[0] << " "
+                  //            << xyz(0) << " "
+                  //            << xyz(1) << " "
+                  //            << fine << " "
+                  //            << coarse << " "
+                  //            << sgn << " "
+                  //            << v(coarse+pp[d]*sgn) << " "
+                  //            << v(coarse) << " "
+                  //            << v(coarse-pp[d]*sgn) << " "
+                  //            << result + dvx_dy << " "
+                  //            << "\n";
+                }
+
+              /* Bottom tip */
+              /* Singularity in coarse+1 */
+              else if(sgn*(xyz(1)+sgn*dx[1]*0.5-y_min)<0 && sgn*(xyz(1)+sgn*dx[1]*2.5-y_min)>0)
+                {
+                  dvx_dy=(v(coarse)-v(coarse-pp[d]*sgn))/4;
+                  // tbox::pout << "refine m cp1 "
+                  //            << 1/dx[0] << " "
+                  //            << xyz(0) << " "
+                  //            << xyz(1) << " "
+                  //            << fine << " "
+                  //            << coarse << " "
+                  //            << sgn << " "
+                  //            << v(coarse+pp[d]*sgn) << " "
+                  //            << v(coarse) << " "
+                  //            << v(coarse-pp[d]*sgn) << " "
+                  //            << result + dvx_dy << " "
+                  //            << "\n";
+                }
+              /* Singularity in coarse */
+              else if(sgn*(xyz(1)-sgn*dx[1]*1.5-y_min)<0 && sgn*(xyz(1)+sgn*dx[1]*0.5-y_min)>0)
+                {
+                  dvx_dy=0;
+                  // tbox::pout << "refine m c "
+                  //            << 1/dx[0] << " "
+                  //            << xyz(0) << " "
+                  //            << xyz(1) << " "
+                  //            << fine << " "
+                  //            << coarse << " "
+                  //            << sgn << " "
+                  //            << v(coarse+pp[d]*sgn) << " "
+                  //            << v(coarse) << " "
+                  //            << v(coarse-pp[d]*sgn) << " "
+                  //            << result + dvx_dy << " "
+                  //            << "\n";
+                }
+              /* Singularity in coarse-1 */
+              else if(sgn*(xyz(1)-sgn*dx[1]*3.5-y_min)<0 && sgn*(xyz(1)-sgn*dx[1]*1.5-y_min)>0)
+                {
+                  dvx_dy=(v(coarse+pp[d]*sgn)-v(coarse))/4;
+                  // tbox::pout << "refine m cm1 "
+                  //            << 1/dx[0] << " "
+                  //            << xyz(0) << " "
+                  //            << xyz(1) << " "
+                  //            << fine << " "
+                  //            << coarse << " "
+                  //            << sgn << " "
+                  //            << v(coarse+pp[d]*sgn) << " "
+                  //            << v(coarse) << " "
+                  //            << v(coarse-pp[d]*sgn) << " "
+                  //            << result + dvx_dy << " "
+                  //            << "\n";
+                }
+
+              // /* Bottom tip */
+              // /* Singularity in coarse+1 */
+              // else if(sgn*(xyz(1)-sgn*dx[1]*1.5-y_min)<0 && sgn*(xyz(1)-sgn*dx[1]*3.5-y_min)>0)
+              //   {
+              //     dvx_dy=(v(coarse)-v(coarse-pp[d]*sgn))/4;
+              //     tbox::pout << "refine m cp1 "
+              //                << 1/dx[0] << " "
+              //                << xyz(0) << " "
+              //                << xyz(1) << " "
+              //                << fine << " "
+              //                << coarse << " "
+              //                << sgn << " "
+              //                << v(coarse+pp[d]*sgn) << " "
+              //                << v(coarse) << " "
+              //                << v(coarse-pp[d]*sgn) << " "
+              //                << result + dvx_dy << " "
+              //                << "\n";
+              //   }
+              // /* Jump in coarse */
+              // else if(sgn*(xyz(1)-sgn*dx[1]*1.5-y_min)>0 && sgn*(xyz(1)+sgn*dx[1]*0.5-y_min)<0)
+              //   {
+              //     dvx_dy=(v(coarse+pp[d]*sgn)-v(coarse))/4;
+              //     tbox::pout << "refine m c "
+              //                << 1/dx[0] << " "
+              //                << xyz(0) << " "
+              //                << xyz(1) << " "
+              //                << fine << " "
+              //                << coarse << " "
+              //                << sgn << " "
+              //                << v(coarse+pp[d]*sgn) << " "
+              //                << v(coarse) << " "
+              //                << v(coarse-pp[d]*sgn) << " "
+              //                << result + dvx_dy << " "
+              //                << "\n";
+              //   }
+
+            }
+
+          // if(coarse[1]==6)
+          //       {
+          //         tbox::pout << "refine "
+          //                    << 1/dx[0] << " "
+          //                    << xyz(0) << " "
+          //                    << xyz(1) << " "
+          //                    << fine << " "
+          //                    << coarse << " "
+          //                    << sgn << " "
+          //                    << v(coarse+pp[d]*sgn) << " "
+          //                    << v(coarse) << " "
+          //                    << v(coarse-pp[d]*sgn) << " "
+          //                    << result + dvx_dy << " "
+          //                    << "\n";
+
+          //       }
+
+
+
+          if(axis==1 && xyz(1)>=0.4 && xyz(1)<=0.6)
+            {
+              /* Interface between fine and coarse+1, do a one-sided
+                 interpolation. */
+              if(sgn*(xyz(0)-0.5)<0 && sgn*(xyz(0)+sgn*1.5*dx[0]-0.5)>0)
+                {
+                  dvx_dy=(v(coarse)-v(coarse-pp[d]*sgn))/4;
+
+                  // tbox::pout << "refine fcp1 "
+                  //            << 1/dx[0] << " "
+                  //            << xyz(0) << " "
+                  //            << xyz(1) << " "
+                  //            << fine << " "
+                  //            << coarse << " "
+                  //            << sgn << " "
+                  //            << v(coarse+pp[d]*sgn) << " "
+                  //            << v(coarse) << " "
+                  //            << v(coarse-pp[d]*sgn) << " "
+                  //            << result + sgn*dvx_dy << " "
+                  //            << "\n";
+                }
+              /* Interface between fine and coarse, use derivative
+                 from the other side. */
+              else if(sgn*(xyz(0)-0.5)>0 && sgn*(xyz(0)-sgn*dx[0]/2-0.5)<0)
+                {
+                  dvx_dy=(v(coarse+pp[d]*sgn)-v(coarse)
+                          - (v(coarse)-v(coarse-pp[d]*sgn))*0.75);
+
+                  // tbox::pout << "refine fc "
+                  //            << 1/dx[0] << " "
+                  //            << xyz(0) << " "
+                  //            << xyz(1) << " "
+                  //            << fine << " "
+                  //            << coarse << " "
+                  //            << sgn << " "
+                  //            << v(coarse+pp[d]*sgn) << " "
+                  //            << v(coarse) << " "
+                  //            << v(coarse-pp[d]*sgn) << " "
+                  //            << result + sgn*dvx_dy << " "
+                  //            << "\n";
+                }
+              /* Interface between coarse and coarse-1, do a one-sided
+                 interpolation. */
+              else if(sgn*(xyz(0)-0.5)>0 && sgn*(xyz(0)-sgn*2.5*dx[0]-0.5)<0)
+                {
+                  dvx_dy=(v(coarse+pp[d]*sgn)-v(coarse))/4;
+
+                  // tbox::pout << "refine ccm1 "
+                  //            << 1/dx[0] << " "
+                  //            << xyz(0) << " "
+                  //            << xyz(1) << " "
+                  //            << fine << " "
+                  //            << coarse << " "
+                  //            << sgn << " "
+                  //            << v(coarse+pp[d]*sgn) << " "
+                  //            << v(coarse) << " "
+                  //            << v(coarse-pp[d]*sgn) << " "
+                  //            << result + sgn*dvx_dy << " "
+                  //            << "\n";
+                }
+            }
+        }
+      result+=dvx_dy;
+    }
+  return result;
+}
+
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/V_Refine_Patch_Strategy.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/V_Refine_Patch_Strategy.h	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,409 @@
+/*************************************************************************
+ *
+ * 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:   Robin boundary condition support on cartesian grids. 
+ *
+ ************************************************************************/
+#ifndef GAMRA_ELASTIC_V_REFINE_PATCH_STRATEGY_H
+#define GAMRA_ELASTIC_V_REFINE_PATCH_STRATEGY_H
+
+#include "SAMRAI/SAMRAI_config.h"
+
+#include "SAMRAI/xfer/RefinePatchStrategy.h"
+#include "SAMRAI/geom/CartesianPatchGeometry.h"
+#include "SAMRAI/pdat/SideData.h"
+#include "SAMRAI/pdat/CellIndex.h"
+#include "Constants.h"
+#include "set_boundary.h"
+
+namespace SAMRAI {
+namespace solv {
+namespace Elastic {
+
+/*!
+ * @brief Helper utility for setting boundary conditions on V.
+ *
+ * This class inherits and implements virtual functions from
+ * xfer::RefinePatchStrategy so it may be used to help create
+ * communication schedules if desired.
+ */
+class V_Refine_Patch_Strategy:
+   public xfer::RefinePatchStrategy
+{
+
+public:
+   /*!
+    * @brief Constructor using.
+    *
+    * @param object_name Name of the object, for general referencing.
+    * @param coef_strategy Coefficients strategy being helped.
+    */
+   V_Refine_Patch_Strategy(
+      const tbox::Dimension& dim,
+      std::string object_name = std::string()):
+     xfer::RefinePatchStrategy(dim), d_dim(dim),d_object_name(object_name) {}
+
+   /*!
+    * @brief Destructor.
+    */
+   virtual ~V_Refine_Patch_Strategy(void) {}
+
+   //@{ @name xfer::RefinePatchStrategy virtuals
+
+   virtual void
+   setPhysicalBoundaryConditions(
+      hier::Patch& ,
+      const double ,
+      const hier::IntVector& ) {}
+   hier::IntVector
+   getRefineOpStencilWidth() const
+  { return hier::IntVector::getOne(d_dim); }
+   // virtual void
+   // preprocessRefineBoxes(
+   //    hier::Patch& fine,
+   //    const hier::Patch& coarse,
+   //    const hier::BoxList& fine_boxes,
+   //    const hier::IntVector& ratio) {}
+   virtual void
+   preprocessRefine(hier::Patch& ,
+                    const hier::Patch& coarse,
+                    const hier::Box& ,
+                    const hier::IntVector& )
+  {
+    set_boundary(coarse,invalid_id,v_id,true);
+  }
+
+   virtual void
+   postprocessRefineBoxes(
+      hier::Patch& ,
+      const hier::Patch& ,
+      const hier::BoxList& ,
+      const hier::IntVector& ) {}
+   virtual void
+   postprocessRefine(
+      hier::Patch& ,
+      const hier::Patch& ,
+      const hier::Box& ,
+      const hier::IntVector& ) {}
+
+   //@}
+
+   //@{
+
+   /*!
+    * @name Functions to set boundary condition values
+    */
+
+   /*!
+    * @brief Set the physical boundary condition by setting the
+    * value of the first ghost cells.
+    *
+    * This function has an interface similar to the virtual function
+    * xfer::RefinePatchStrategy::setPhysicalBoundaryConditions(),
+    * and it may be used to help implement that function,
+    * but it does not serve the same purpose.  The primary
+    * differences are:
+    * -# It specializes to cell-centered variables.
+    * -# Only one ghost cell width is filled.  Setting a Robin
+    *    boundary condition for cell-centered quantities requires
+    *    only one ghost cell to be set.
+    *    (More ghost cells can be filled by continuing the linear
+    *    distribution of data beyond the first cell, but that is
+    *    not implemented at this time.)
+    * -# User must specify the index of the data whose ghost
+    *    cells need to be filled.  This index is used to determine
+    *    the variable for which to set the boundary coefficients
+    *    and to get the data to be set.
+    *
+    * This function calls RobinBcStrategy::setBcCoefs() to
+    * get the coefficients, then it sets the values in the first
+    * ghost cell on the boundary.
+    *
+    * To determine the value for the ghost cell,
+    * a @em linear approximation in the direction normal to the
+    * boundary is assumed.  We write the following discrete
+    * approximations:
+    * @f[ u_b = \frac{ u_i + u_o }{2} @f]
+    * @f[ [u_n]_b = \frac{ u_o - u_i }{h} @f]
+    * where the subscript b stands for the the boundary,
+    * i stands for the first cell inside the boundary and
+    * o stands for the first cell outside the boundary
+    * and h is the grid spacing normal to the boundary.
+    * Applying this to the Robin formula gives
+    * @f[ u_o = \frac{ h\gamma + u_i( \beta - \frac{h}{2} \alpha ) }
+    * { \beta + \frac{h}{2} \alpha } @f] or equivalently
+    * @f[ u_o = \frac{ hg + u_i (1-a(1+\frac{h}{2})) }{ 1-a(1-\frac{h}{2}) } @f]
+    *
+    * After setting the edge (face in 3D) boundary conditions,
+    * linear approximations are used to set the boundary conditions
+    * of higher boundary types (nodes in 2D, edges and nodes in 3D).
+    *
+    * In some cases, the calling function wants to set the
+    * boundary condition homogeneously, with g=0.
+    * This is useful in problems where the the solution of the
+    * homogeneous problem is required in solving the inhomogeneous
+    * problem.  This function respects such requests specified
+    * through the argument @c homogeneous_bc.
+    *
+    * @internal To be more general to other data types,
+    * there could be versions for other data types also,
+    * such as ...InNodes, ...InFaces, etc.  However, I'm not
+    * sure exactly how to implement the Robin boundary condition
+    * on the faces and nodes when m != 1.  Should the boundary
+    * value be set or should the first ghost value be set?
+    *
+    * @internal I have not addressed possibility of differences
+    * in chosing the discrete formulation with which to compute
+    * the boundary value.  The above formulation is obviously
+    * one specific approximation, but there could be others.
+    * If anoter approximation is required, there should be
+    * another class like this or this class can offer a choice
+    * to be set by the user.  I favor another class.
+    *
+    * @internal Since the data alignment can be found through
+    * the target_data_id, these types of functions may be changed
+    * to just plain setBoundaryValues or setBoundaryValuesInBoundaryBoxes
+    * since it does assume boundary boxes.  This may have to be
+    * expanded to later include coarse-fine boundary boxes
+    * for more generality.
+    *
+    * @param patch hier::Patch on which to set boundary condition
+    * @param fill_time Solution time corresponding to filling
+    * @param ghost_width_to_fill Max ghost width requiring fill
+    * @param target_data_id hier::Patch data index of data to be set.
+    *        This data must be a cell-centered double.
+    * @param homogeneous_bc Set a homogeneous boundary condition.
+    *    This means g=0 for the boundary.
+    */
+   // void
+   // setBoundaryValuesInCells(
+   //    hier::Patch& patch,
+   //    const double fill_time,
+   //    const hier::IntVector& ghost_width_to_fill,
+   //    int target_data_id,
+   //    bool homogeneous_bc = false) const;
+
+   /*!
+    * @brief Set ghost cells for an entire level.
+    *
+    * Loop through all patches on the given level and call
+    * setBoundaryValuesInCells(hier::Patch &patch,
+    *                          const double fill_time ,
+    *                          const hier::IntVector &ghost_width_to_fill ,
+    *                          int target_data_id ,
+    *                          bool homogeneous_bc=false )
+    * for each.
+    *
+    * @param level PatchLevel on which to set boundary condition
+    * @param fill_time Solution time corresponding to filling
+    * @param ghost_width_to_fill Max ghost width requiring fill
+    * @param target_data_id hier::Patch data index of data to be set.
+    *        This data must be a cell-centered double.
+    * @param homogeneous_bc Set a homogeneous boundary condition.
+    *    This means g=0 for the boundary.
+    */
+   // void
+   // setBoundaryValuesInCells(
+   //    hier::PatchLevel& level,
+   //    const double fill_time,
+   //    const hier::IntVector& ghost_width_to_fill,
+   //    int target_data_id,
+   //    bool homogeneous_bc = false) const;
+
+   /*!
+    * @brief Set the physical boundary condition by setting the
+    * value of the boundary nodes.
+    *
+    * This function is not yet implemented!
+    *
+    * There are some decisions that must be made before
+    * the implementation can be written.
+    * -# Do we set the values on the boundary or one cell
+    *    away from the boundary?
+    * -# What is the discrete formulation we should use
+    *    to compute the value to be set?
+    *
+    * This function has an interface similar to the virtual function
+    * xfer::RefinePatchStrategy::setPhysicalBoundaryConditions(),
+    * and it may be used to help implement that function,
+    * but it does not serve the same purpose.  The primary
+    * differences are:
+    * -# It specializes to node-centered variables.
+    * -# User must specify the index of the data whose ghost
+    *    cells need to be filled.  This index is used to determine
+    *    the variable for which to set the boundary coefficients
+    *    and to get the data to be set.
+    *
+    * This function calls RobinBcStrategy::setBcCoefs() to get the
+    * coefficients, then it sets the values at the boundary nodes.
+    *
+    * In some cases, the calling function wants to set the
+    * boundary condition homogeneously, with g=0.
+    * This is useful in problems where the the solution of the
+    * homogeneous problem is required to solving the inhomogeneous
+    * problem.  This function respects such requests specified
+    * through the argument @c homogeneous_bc.
+    *
+    * @param patch hier::Patch on which to set boundary condition
+    * @param fill_time Solution time corresponding to filling
+    * @param target_data_id hier::Patch data index of data to be set.
+    * @param homogeneous_bc Set a homogeneous boundary condition.
+    *    This means g=0 for the boundary.
+    */
+   // void
+   // setBoundaryValuesAtNodes(
+   //    hier::Patch& patch,
+   //    const double fill_time,
+   //    int target_data_id,
+   //    bool homogeneous_bc = false) const;
+
+   //@}
+
+   //@{
+   /*!
+    * @name Ways to provide the Robin bc coefficients
+    */
+
+   /*!
+    * @brief Provide an implementation of the RobinBcCoefStrategy
+    * for determining the boundary coefficients.
+    *
+    * Provide the implementation that can be used to set the
+    * Robin bc coefficients.
+    *
+    * @param coef_strategy tbox::Pointer to a concrete inmplementation of
+    *        the coefficient strategy.
+    */
+   // void
+   // setCoefImplementation(
+   //    const RobinBcCoefStrategy* coef_strategy);
+
+   /*!
+    * @brief Set the data id that should be filled when setting
+    * physical boundary conditions.
+    *
+    * When setPhysicalBoundaryConditions is called, the data
+    * specified will be set.  This information is required because
+    * the it is not passed in through the argument list of
+    * setPhysicalBounaryConditions.
+    */
+  void setTargetDataId(int id)
+  {
+    v_id=id;
+  }
+
+   /*!
+    * @brief Set whether boundary filling should assume homogeneous
+    * conditions.
+    *
+    * In certain circumstances, only the value of a is needed, while
+    * the value of g is temporarily not required and taken to be zero.
+    * (An example is in setting the boundary condition for error
+    * value in an iterative method.)  In such cases, use this function
+    * to set a flag that will cause a null pointer to be given to
+    * setBcCoefs() to indicate that fact.
+    */
+   // void
+   // setHomogeneousBc(
+   //    bool homogeneous_bc);
+
+   //@}
+
+private:
+   /*!
+    * @brief Trim a boundary box so that it does not stick out
+    * past a given box.
+    *
+    * Certain boundary-related operations occur on patch data that
+    * do not or cannot extend past the edgr or corner of a patch.
+    * This function is used to trim down the parts of the boundary box
+    * that extend past those points so that a suitable index range
+    * is achieved.
+    *
+    * The boundary box trimmed must be of type 1 or 2.
+    *
+    * @param boundary_box Boundary box to be trimmed.
+    * @param limit_box hier::Box to not stick past
+    *
+    * @return New trimmed boundary box.
+    */
+   // hier::BoundaryBox
+   // trimBoundaryBox(
+   //    const hier::BoundaryBox& boundary_box,
+   //    const hier::Box& limit_box) const;
+
+   /*!
+    * @brief Return box describing the index space of boundary nodes
+    * defined by a boundary box.
+    *
+    * Define a box describing the indices of the nodes corresponding
+    * to the input boundary box.  These nodes lie on the boundary
+    * itself.
+    *
+    * The input boundary_box must be of type 1
+    * (see hier::BoundaryBox::getBoundaryType()).
+    *
+    * @param boundary_box input boundary box
+    * @return a box to define the node indices corresponding to
+    *   boundary_box
+    */
+   // hier::Box
+   // makeNodeBoundaryBox(
+   //    const hier::BoundaryBox& boundary_box) const;
+
+   /*!
+    * @brief Return box describing the index space of faces
+    * defined by a boundary box.
+    *
+    * Define a box describing the indices of the codimension 1
+    * surface corresponding to the input boundary box.
+    *
+    * The input boundary_box must be of type 1
+    * (see hier::BoundaryBox::getBoundaryType()).
+    *
+    * This is a utility function for working with the
+    * indices coresponding to a boundary box but coincide
+    * with the patch boundary.
+    *
+    * @param boundary_box input boundary box
+    * @return a box to define the face indices corresponding to
+    *    boundary_box
+    */
+   // hier::Box
+   // makeFaceBoundaryBox(
+   //    const hier::BoundaryBox& boundary_box) const;
+
+   const tbox::Dimension d_dim;
+
+   std::string d_object_name;
+
+   /*!
+    * @brief Coefficient strategy giving a way to get to
+    * Robin bc coefficients.
+    */
+   // const RobinBcCoefStrategy* d_coef_strategy;
+
+   /*!
+    * @brief hier::Index of target patch data when filling ghosts.
+    */
+   int v_id;
+
+   /*!
+    * @brief Whether to assumg g=0 when filling ghosts.
+    */
+   // bool d_homogeneous_bc;
+
+   /*!
+    * @brief Timers for performance measurement.
+    */
+   // tbox::Pointer<tbox::Timer> t_set_boundary_values_in_cells;
+   // tbox::Pointer<tbox::Timer> t_use_set_bc_coefs;
+};
+
+}
+}
+}
+#endif  // included_solv_V_Refine_Patch_Strategy
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/dRc_dp.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/dRc_dp.h	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,61 @@
+#ifndef GAMR_DRC_DP_H
+#define GAMR_DRC_DP_H
+
+#include "SAMRAI/pdat/CellData.h"
+#include "SAMRAI/pdat/NodeData.h"
+#include "SAMRAI/pdat/SideData.h"
+#include "dRm_dv.h"
+#include "Constants.h"
+
+/* These two functions should really have a more similar API */
+
+/* The derivative of the continuity equation with respect to
+   pressure.  Note that pressure does not appear in the continuity
+   equation, so we use Tackley's method to chain together
+   derivatives */
+
+inline double dRc_dp_2D(const SAMRAI::hier::Box &pbox,
+                        const SAMRAI::pdat::CellIndex &center,
+                        const SAMRAI::pdat::SideIndex &x,
+                        const SAMRAI::pdat::SideIndex &y,
+                        SAMRAI::pdat::CellData<double> &cell_moduli,
+                        SAMRAI::pdat::NodeData<double> &edge_moduli,
+                        SAMRAI::pdat::SideData<double> &v,
+                        const double &dx,
+                        const double &dy)
+{
+  const SAMRAI::hier::Index ip(1,0), jp(0,1);
+  const SAMRAI::pdat::NodeIndex
+    center_e(center,SAMRAI::pdat::NodeIndex::LowerLeft),
+    up_e(center_e+jp),right_e(center_e+ip);
+    
+  const double dRm_dp_xp(1/dx), dRm_dp_xm(-1/dx),
+    dRm_dp_yp(1/dy), dRm_dp_ym(-1/dy),
+    dRc_dvx_p(-1/dx), dRc_dvx_m(1/dx),
+    dRc_dvy_p(-1/dy), dRc_dvy_m(1/dy);
+
+  double result(0);
+
+  if(!(center[0]==pbox.lower(0) && v(x-ip)==boundary_value))
+    result+=dRc_dvx_m * dRm_dp_xm/dRm_dv_2D(cell_moduli,edge_moduli,
+                                            center,center-ip,up_e,center_e,
+                                            dx,dy);
+
+  if(!(center[0]==pbox.upper(0) && v(x+ip*2)==boundary_value))
+    result+=dRc_dvx_p * dRm_dp_xp/dRm_dv_2D(cell_moduli,edge_moduli,
+                                            center+ip,center,up_e+ip,
+                                            center_e+ip,dx,dy);
+  if(!(center[1]==pbox.lower(1) && v(y-jp)==boundary_value))
+    result+=dRc_dvy_m * dRm_dp_ym/dRm_dv_2D(cell_moduli,edge_moduli,
+                                            center,center-jp,right_e,center_e,
+                                            dy,dx);
+
+  if(!(center[1]==pbox.upper(1) && v(y+jp*2)==boundary_value))
+    result+=dRc_dvy_p * dRm_dp_yp/dRm_dv_2D(cell_moduli,edge_moduli,
+                                            center+jp,center,right_e+jp,
+                                            center_e+jp,dy,dx);
+                                            
+  return result;
+}
+
+#endif
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/dRm_dv.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/dRm_dv.h	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,42 @@
+#ifndef GAMR_DRM_DV_H
+#define GAMR_DRM_DV_H
+
+#include "SAMRAI/pdat/CellData.h"
+#include "SAMRAI/pdat/EdgeData.h"
+
+/* The derivative of the momentum equation w/respect to velocity. It
+   is written from the perspective of vx(center_x), but pass in
+   different values for center etc. to get vy or vx(!center_x). */
+
+template<class E_data, class E_index>
+double dRm_dv_2D(SAMRAI::pdat::CellData<double> &cell_moduli,
+                 E_data &edge_moduli,
+                 const SAMRAI::pdat::CellIndex &center,
+                 const SAMRAI::pdat::CellIndex &left,
+                 const E_index &up_e,
+                 const E_index &center_e,
+                 const double &dx,
+                 const double &dy)
+{
+  return -(   (cell_moduli(center,0) + cell_moduli(left,0))
+           +2*(cell_moduli(center,1) + cell_moduli(left,1)))/(dx*dx)
+         -(edge_moduli(up_e,1) + edge_moduli(center_e,1))/(dy*dy);
+}
+
+inline double dRm_dv_3D(SAMRAI::pdat::CellData<double> &cell_moduli,
+		        SAMRAI::pdat::EdgeData<double> &edge_moduli,
+			const SAMRAI::pdat::CellIndex &center,
+			const SAMRAI::pdat::CellIndex &left,
+			const SAMRAI::pdat::EdgeIndex &front_y,
+			const SAMRAI::pdat::EdgeIndex &center_y,
+			const SAMRAI::pdat::EdgeIndex &up_z,
+			const SAMRAI::pdat::EdgeIndex &center_z,
+			const double &dx,
+			const double &dy,
+			const double &dz)
+{
+	  return dRm_dv_2D(cell_moduli,edge_moduli,center,left,front_y,center_y,dx,dy)
+		      - (edge_moduli(up_z,1) + edge_moduli(center_z,1))/(dz*dz);
+}
+
+#endif
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/set_boundary.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/set_boundary.C	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,168 @@
+#include "set_boundary.h"
+#include "Constants.h"
+#include "SAMRAI/tbox/Pointer.h"
+#include "SAMRAI/pdat/SideData.h"
+#include "SAMRAI/pdat/CellData.h"
+#include "SAMRAI/geom/CartesianPatchGeometry.h"
+
+using namespace SAMRAI;
+
+void set_boundary(const SAMRAI::hier::Patch& patch, const int &p_id,
+                    const int &v_id, const bool &rhs)
+{
+  hier::Box pbox=patch.getBox();
+
+  tbox::Pointer<geom::CartesianPatchGeometry> geom = patch.getPatchGeometry();
+  const tbox::Dimension Dim(patch.getDim());
+  const int dim(patch.getDim().getValue());
+
+  const hier::Index zero(hier::Index::getZeroIndex(Dim));
+  hier::Index pp[]={zero,zero,zero};
+  for(int i=0;i<dim;++i)
+    pp[i][i]=1;
+  /* This should really get read from the input file. */
+  double lower_boundary[]={0,0,0};
+  bool lower_dirichlet[]={true,true,true};
+
+  // double upper_boundary[]={-6.94444444444e4,0,0};
+  // bool upper_dirichlet[]={true,false,true};
+
+  // bool upper_dirichlet[]={true,true,true};
+  // double upper_boundary[]={-1,1,0};
+
+  double p_lower[]={0,0,0};
+  double p_upper[]={0,0,0};
+
+  bool upper_dirichlet[]={true,true,true};
+  double upper_boundary[]={0,0,0};
+
+  if(v_id!=invalid_id)
+    {
+      tbox::Pointer<pdat::SideData<double> > v_ptr = patch.getPatchData(v_id);
+      pdat::SideData<double> &v(*v_ptr);
+
+      hier::Box gbox=v.getGhostBox();
+      for(int ix=0; ix<dim; ++ix)
+        {
+          for(pdat::SideIterator si(gbox,ix); si; si++)
+            {
+              pdat::SideIndex x(*si);
+
+              /* Set a sentinel value for normal components */
+              if(x[ix]<pbox.lower(ix) && geom->getTouchesRegularBoundary(ix,0))
+                {
+                  if(lower_dirichlet[ix])
+                    v(x)=boundary_value;
+                  else
+                    v(x)=v(x+pp[ix]*2);
+                }
+              else if(x[ix]>pbox.upper(ix)+1
+                      && geom->getTouchesRegularBoundary(ix,1))
+                {
+                  if(upper_dirichlet[ix])
+                    v(x)=boundary_value;
+                  else
+                    v(x)=v(x-pp[ix]*2);
+                }
+              /* Set values for normal components */
+              else if(x[ix]==pbox.lower(ix)
+                      && geom->getTouchesRegularBoundary(ix,0)
+                      && !rhs && lower_dirichlet[ix])
+                {
+                  v(x)=lower_boundary[ix];
+                }
+              else if(x[ix]==pbox.upper(ix)+1
+                      && geom->getTouchesRegularBoundary(ix,1)
+                      && !rhs && upper_dirichlet[ix])
+                {
+                  v(x)=upper_boundary[ix];
+                }
+              /* Set derivatives for tangential component.  The edges
+                 and corners are incorrect for now.  */
+              else
+                {
+                  for(int iy=(ix+1)%dim; iy!=ix; iy=(iy+1)%dim)
+                    {
+                      if(x[iy]<pbox.lower(iy)
+                         && geom->getTouchesRegularBoundary(iy,0))
+                        {
+                          v(x)=v(x+pp[iy]);
+                        }
+                      else if(x[iy]>pbox.upper(iy)
+                              && geom->getTouchesRegularBoundary(iy,1))
+                        {
+                          v(x)=v(x-pp[iy]);
+                        }
+                    }
+                }
+            }
+          /* Fix up the edges.  This has to be done in a different
+             loop, because the values on the faces will be used to
+             compute values in the edges and corners.  In 2D, I am not
+             sure that this is needed.  It is certainly not needed if
+             we have dirichlet conditions on the boundary.  It is
+             definitely needed in 3D.  We use the d/dx conditions
+             here, though we could use the d/dy conditions and get the
+             same number, as long as we have pure Neumann boundary
+             conditions, and not Robin. */
+
+          for(pdat::SideIterator si(gbox,ix); si; si++)
+            {
+              pdat::SideIndex x(*si);
+              if((x[ix]<pbox.lower(ix)
+                  && geom->getTouchesRegularBoundary(ix,0)
+                  && !lower_dirichlet[ix])
+                 || (x[ix]>pbox.upper(ix)+1
+                     && geom->getTouchesRegularBoundary(ix,1)
+                     && !upper_dirichlet[ix]))
+                {
+                  for(int iy=(ix+1)%dim; iy!=ix; iy=(iy+1)%dim)
+                    {
+                      if(x[iy]<pbox.lower(iy) 
+                         && geom->getTouchesRegularBoundary(iy,0))
+                        {
+                          v(x)=v(x+pp[iy]);
+                        }
+                      else if(x[iy]>pbox.upper(iy) 
+                              && geom->getTouchesRegularBoundary(iy,1))
+                        {
+                          v(x)=v(x-pp[iy]);
+                        }
+                    }
+                }
+            }
+          /* In 3D, fix the corners.  I am not sure that this is
+             needed. */
+          if(dim==3)
+            {
+              const int iy((ix+1)%dim), iz((iy+1)%dim);
+              for(pdat::SideIterator si(gbox,ix); si; si++)
+                {
+                  pdat::SideIndex x(*si);
+                  if(((x[ix]<pbox.lower(ix)
+                       && geom->getTouchesRegularBoundary(ix,0)
+                       && !lower_dirichlet[ix])
+                      || (x[ix]>pbox.upper(ix)+1
+                          && geom->getTouchesRegularBoundary(ix,1)
+                          && !upper_dirichlet[ix]))
+                     && ((x[iy]<pbox.lower(iy)
+                          && geom->getTouchesRegularBoundary(iy,0))
+                         || (x[iy]>pbox.upper(iy) 
+                             && geom->getTouchesRegularBoundary(iy,1))))
+                    {
+                      if(x[iz]<pbox.lower(iz) 
+                         && geom->getTouchesRegularBoundary(iz,0))
+                        {
+                          v(x)=v(x+pp[iz]);
+                        }
+                      else if(x[iz]>pbox.upper(iz) 
+                              && geom->getTouchesRegularBoundary(iz,1))
+                        {
+                          v(x)=v(x-pp[iz]);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff -r 2816cd6f8030 -r c77b196abc8c src/Elastic/set_boundary.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Elastic/set_boundary.h	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,9 @@
+#ifndef GAMRA_ELASTIC_SET_BOUNDARY_H
+#define GAMRA_ELASTIC_SET_BOUNDARY_H
+
+#include "SAMRAI/hier/Patch.h"
+
+void set_boundary(const SAMRAI::hier::Patch& patch,
+                  const int &p_id, const int &v_id, const bool &rhs);
+
+#endif
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/FAC.h
--- a/src/Stokes/FAC.h	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/FAC.h	Thu Jun 07 13:34:24 2012 -0700
@@ -7,8 +7,8 @@
  * Description:   Numerical routines for example FAC Stokes solver 
  *
  ************************************************************************/
-#ifndef included_Stokes_FAC
-#define included_Stokes_FAC
+#ifndef GAMRA_STOKES_FAC_H
+#define GAMRA_STOKES_FAC_H
 
 #include "Stokes/FACSolver.h"
 #include "SAMRAI/pdat/CellVariable.h"
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/FAC/FAC.C
--- a/src/Stokes/FAC/FAC.C	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/FAC/FAC.C	Thu Jun 07 13:34:24 2012 -0700
@@ -22,32 +22,34 @@
 
 namespace SAMRAI {
 
-  /* A little utility routine to validate the sizes of input arrays */
-  void check_array_sizes(const tbox::Array<int> ijk,
-                         const tbox::Array<double> min,
-                         const tbox::Array<double> max,
-                         const tbox::Array<double> data,
-                         const int dim, const std::string &name,
-                         const int num_components=1)
-  {
-    if(ijk.size()!=dim)
-      TBOX_ERROR("Bad number of elements in " << name << "_ijk.  Expected "
-                 << dim << " but got " << ijk.size());
-    if(min.size()!=dim)
-      TBOX_ERROR("Bad number of elements in "
-                 << name << "_coord_min.  Expected "
-                 << dim << " but got " << min.size());
-    if(max.size()!=dim)
-      TBOX_ERROR("Bad number of elements in "
-                 << name << "_coord_max.  Expected "
-                 << dim << " but got " << max.size());
-    int data_size(1);
-    for(int d=0; d<dim; ++d)
-      data_size*=ijk[d];
-    if(data.size()!=data_size*num_components)
-      TBOX_ERROR("Bad number of elements in "
-                 << name << "_data.  Expected "
-                 << data_size << " but got " << data.size());
+  namespace Stokes {
+    /* A little utility routine to validate the sizes of input arrays */
+    void check_array_sizes(const tbox::Array<int> ijk,
+                           const tbox::Array<double> min,
+                           const tbox::Array<double> max,
+                           const tbox::Array<double> data,
+                           const int dim, const std::string &name,
+                           const int num_components=1)
+    {
+      if(ijk.size()!=dim)
+        TBOX_ERROR("Bad number of elements in " << name << "_ijk.  Expected "
+                   << dim << " but got " << ijk.size());
+      if(min.size()!=dim)
+        TBOX_ERROR("Bad number of elements in "
+                   << name << "_coord_min.  Expected "
+                   << dim << " but got " << min.size());
+      if(max.size()!=dim)
+        TBOX_ERROR("Bad number of elements in "
+                   << name << "_coord_max.  Expected "
+                   << dim << " but got " << max.size());
+      int data_size(1);
+      for(int d=0; d<dim; ++d)
+        data_size*=ijk[d];
+      if(data.size()!=data_size*num_components)
+        TBOX_ERROR("Bad number of elements in "
+                   << name << "_data.  Expected "
+                   << data_size << " but got " << data.size());
+    }
   }
   /*
 *************************************************************************
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/FACOps.h
--- a/src/Stokes/FACOps.h	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/FACOps.h	Thu Jun 07 13:34:24 2012 -0700
@@ -7,8 +7,8 @@
  * Description:   Operator class for cell-centered scalar Stokes using FAC 
  *
  ************************************************************************/
-#ifndef included_solv_StokesFACOps
-#define included_solv_StokesFACOps
+#ifndef GAMRA_STOKES_FACOPS_H
+#define GAMRA_STOKES_FACOPS_H
 
 #include "SAMRAI/SAMRAI_config.h"
 
@@ -41,9 +41,9 @@
 #include "SAMRAI/tbox/Database.h"
 #include "SAMRAI/tbox/Pointer.h"
 #include "SAMRAI/tbox/Timer.h"
-#include "P_Refine_Patch_Strategy.h"
-#include "V_Refine_Patch_Strategy.h"
-#include "V_Coarsen_Patch_Strategy.h"
+#include "Stokes/P_Refine_Patch_Strategy.h"
+#include "Stokes/V_Refine_Patch_Strategy.h"
+#include "Stokes/V_Coarsen_Patch_Strategy.h"
 
 #include <string>
 
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/FACSolver.h
--- a/src/Stokes/FACSolver.h	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/FACSolver.h	Thu Jun 07 13:34:24 2012 -0700
@@ -7,8 +7,8 @@
  * Description:   High-level solver (wrapper) for scalar stokes equation. 
  *
  ************************************************************************/
-#ifndef included_solv_StokesFACSolver
-#define included_solv_StokesFACSolver
+#ifndef GAMRA_STOKES_FACSOLVER_H
+#define GAMRA_STOKES_FACSOLVER_H
 
 #include "SAMRAI/SAMRAI_config.h"
 
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/FACSolver/FACSolver.C
--- a/src/Stokes/FACSolver/FACSolver.C	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/FACSolver/FACSolver.C	Thu Jun 07 13:34:24 2012 -0700
@@ -7,9 +7,6 @@
  * 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 "Stokes/FACSolver.h"
 #include "SAMRAI/tbox/PIO.h"
@@ -159,4 +156,3 @@ namespace SAMRAI {
 
   }
 }
-#endif
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/HypreSolver.C
--- a/src/Stokes/HypreSolver.C	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/HypreSolver.C	Thu Jun 07 13:34:24 2012 -0700
@@ -7,9 +7,6 @@
  * Description:   Hypre solver interface for diffusion-like elliptic problems. 
  *
  ************************************************************************/
-#ifndef included_solv_StokesHypreSolver_C
-#define included_solv_StokesHypreSolver_C
-
 #include "Stokes/HypreSolver.h"
 
 #ifdef HAVE_HYPRE
@@ -1546,4 +1543,3 @@ Stokes::HypreSolver::finalizeCallback()
 }
 
 #endif
-#endif
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/HypreSolver.h
--- a/src/Stokes/HypreSolver.h	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/HypreSolver.h	Thu Jun 07 13:34:24 2012 -0700
@@ -7,14 +7,14 @@
  * Description:   Hypre solver interface for diffusion-like elliptic problems. 
  *
  ************************************************************************/
-#ifndef included_solv_StokesHypreSolver
-#define included_solv_StokesHypreSolver
+#ifndef GAMRA_STOKES_HYPRESOLVER_H
+#define GAMRA_STOKES_HYPRESOLVER_H
 
 #include "SAMRAI/SAMRAI_config.h"
 
 #ifdef HAVE_HYPRE
 
-#ifndef included_HYPRE_struct_ls
+#ifndef GAMRA_STOKES_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
@@ -25,7 +25,7 @@
 #undef F77_FUNC_
 #endif
 #include "HYPRE_struct_ls.h"
-#define included_HYPRE_struct_ls
+#define GAMRA_STOKES_HYPRE_STRUCT_LS
 #endif
 
 #include "SAMRAI/solv/GhostCellRobinBcCoefs.h"
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/P_Boundary_Refine.h
--- a/src/Stokes/P_Boundary_Refine.h	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/P_Boundary_Refine.h	Thu Jun 07 13:34:24 2012 -0700
@@ -9,8 +9,8 @@
  *
  ************************************************************************/
 
-#ifndef included_geom_P_Boundary_Refine
-#define included_geom_P_Boundary_Refine
+#ifndef GAMRA_STOKES_P_BOUNDARY_REFINE_H
+#define GAMRA_STOKES_P_BOUNDARY_REFINE_H
 
 #include "SAMRAI/SAMRAI_config.h"
 
@@ -26,6 +26,7 @@
 
 namespace SAMRAI {
 namespace geom {
+namespace Stokes {
 
 /**
  * Class P_Boundary_Refine implements the special interpolation needed
@@ -135,4 +136,5 @@ private:
 
 }
 }
+}
 #endif
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/P_Boundary_Refine/Update_P_2D.C
--- a/src/Stokes/P_Boundary_Refine/Update_P_2D.C	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/P_Boundary_Refine/Update_P_2D.C	Thu Jun 07 13:34:24 2012 -0700
@@ -39,7 +39,7 @@
 */
      
 
-void SAMRAI::geom::P_Boundary_Refine::Update_P_2D
+void SAMRAI::geom::Stokes::P_Boundary_Refine::Update_P_2D
 (const pdat::CellIndex &fine,
  const hier::Index &ip, const hier::Index &jp,
  const int &j, const int &j_max,
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/P_Boundary_Refine/Update_P_3D.C
--- a/src/Stokes/P_Boundary_Refine/Update_P_3D.C	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/P_Boundary_Refine/Update_P_3D.C	Thu Jun 07 13:34:24 2012 -0700
@@ -47,7 +47,7 @@
 */
      
 
-void SAMRAI::geom::P_Boundary_Refine::Update_P_3D
+void SAMRAI::geom::Stokes::P_Boundary_Refine::Update_P_3D
 (const pdat::CellIndex &fine,
  const hier::Index &ip, const hier::Index &jp, const hier::Index &kp,
  const int &j, const int &k, const int &j_max, const int &k_max,
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/P_Boundary_Refine/refine.C
--- a/src/Stokes/P_Boundary_Refine/refine.C	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/P_Boundary_Refine/refine.C	Thu Jun 07 13:34:24 2012 -0700
@@ -2,13 +2,13 @@
 #include "Stokes/set_boundary.h"
 #include "Constants.h"
 
-void SAMRAI::geom::P_Boundary_Refine::refine(hier::Patch& fine,
-                                             const hier::Patch& coarse,
-                                             const int dst_component,
-                                             const int src_component,
-                                             const hier::BoxOverlap& overlap,
-                                             const hier::IntVector& ratio)
-  const
+void SAMRAI::geom::Stokes::P_Boundary_Refine::refine
+(hier::Patch& fine,
+ const hier::Patch& coarse,
+ const int dst_component,
+ const int src_component,
+ const hier::BoxOverlap& overlap,
+ const hier::IntVector& ratio) const
 {
   const pdat::CellOverlap* t_overlap =
     dynamic_cast<const pdat::CellOverlap *>(&overlap);
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/P_Refine.C
--- a/src/Stokes/P_Refine.C	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/P_Refine.C	Thu Jun 07 13:34:24 2012 -0700
@@ -9,9 +9,6 @@
  *
  ************************************************************************/
 
-#ifndef included_geom_P_Refine_C
-#define included_geom_P_Refine_C
-
 #include "P_Refine.h"
 
 #include <float.h>
@@ -22,7 +19,7 @@
 #include "SAMRAI/pdat/CellVariable.h"
 #include "SAMRAI/tbox/Utilities.h"
 
-void SAMRAI::geom::P_Refine::refine(
+void SAMRAI::geom::Stokes::P_Refine::refine(
    hier::Patch& fine,
    const hier::Patch& coarse,
    const int dst_component,
@@ -46,7 +43,7 @@ void SAMRAI::geom::P_Refine::refine(
    }
 }
 
-void SAMRAI::geom::P_Refine::refine(
+void SAMRAI::geom::Stokes::P_Refine::refine(
    hier::Patch& fine_patch,
    const hier::Patch& coarse_patch,
    const int dst_component,
@@ -116,4 +113,3 @@ void SAMRAI::geom::P_Refine::refine(
          }           
        }
 }
-#endif
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/P_Refine.h
--- a/src/Stokes/P_Refine.h	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/P_Refine.h	Thu Jun 07 13:34:24 2012 -0700
@@ -9,8 +9,8 @@
  *
  ************************************************************************/
 
-#ifndef included_geom_P_Refine
-#define included_geom_P_Refine
+#ifndef GAMRA_STOKES_P_REFINE_H
+#define GAMRA_STOKES_P_REFINE_H
 
 #include "SAMRAI/SAMRAI_config.h"
 
@@ -25,7 +25,7 @@
 
 namespace SAMRAI {
 namespace geom {
-
+namespace Stokes {
 /**
  * Class P_Refine implements linear
  * interpolation for cell-centered double patch data defined over a Cartesian
@@ -139,4 +139,5 @@ private:
 
 }
 }
+}
 #endif
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/P_Refine_Patch_Strategy.h
--- a/src/Stokes/P_Refine_Patch_Strategy.h	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/P_Refine_Patch_Strategy.h	Thu Jun 07 13:34:24 2012 -0700
@@ -7,8 +7,8 @@
  * Description:   Robin boundary condition support on cartesian grids. 
  *
  ************************************************************************/
-#ifndef included_solv_P_Refine_Patch_Strategy
-#define included_solv_P_Refine_Patch_Strategy
+#ifndef GAMRA_STOKES_P_REFINE_PATCH_STRATEGY_H
+#define GAMRA_STOKES_P_REFINE_PATCH_STRATEGY_H
 
 #include "SAMRAI/SAMRAI_config.h"
 
@@ -21,6 +21,7 @@
 
 namespace SAMRAI {
 namespace solv {
+namespace Stokes {
 
 /*!
  * @brief Helper utility for setting boundary conditions on P.
@@ -404,5 +405,6 @@ private:
 
 }
 }
+}
 
 #endif  // included_solv_P_Refine_Patch_Strategy
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/Resid_Coarsen.h
--- a/src/Stokes/Resid_Coarsen.h	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/Resid_Coarsen.h	Thu Jun 07 13:34:24 2012 -0700
@@ -1,5 +1,5 @@
-#ifndef included_geom_Stokes_Resid_Coarsen
-#define included_geom_Stokes_Resid_Coarsen
+#ifndef GAMRA_STOKES_STOKES_RESID_COARSEN_H
+#define GAMRA_STOKES_STOKES_RESID_COARSEN_H
 
 #include "SAMRAI/xfer/CoarsenOperator.h"
 #include "SAMRAI/pdat/CellVariable.h"
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/V_Boundary_Refine.h
--- a/src/Stokes/V_Boundary_Refine.h	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/V_Boundary_Refine.h	Thu Jun 07 13:34:24 2012 -0700
@@ -26,6 +26,7 @@
 
 namespace SAMRAI {
 namespace geom {
+namespace Stokes {
 
 /**
  * Class V_Boundary_Refine implements the special interpolation needed
@@ -161,4 +162,5 @@ private:
 
 }
 }
+}
 #endif
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/V_Boundary_Refine/Update_V_2D.C
--- a/src/Stokes/V_Boundary_Refine/Update_V_2D.C	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/V_Boundary_Refine/Update_V_2D.C	Thu Jun 07 13:34:24 2012 -0700
@@ -4,7 +4,7 @@
 
 /* This is written from the perspective of axis==x.  For axis==y, we
    switch i and j and everything works out. */
-void SAMRAI::geom::V_Boundary_Refine::Update_V_2D
+void SAMRAI::geom::Stokes::V_Boundary_Refine::Update_V_2D
 (const int &axis,
  const int &boundary_direction,
  const bool &boundary_positive,
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/V_Boundary_Refine/Update_V_3D.C
--- a/src/Stokes/V_Boundary_Refine/Update_V_3D.C	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/V_Boundary_Refine/Update_V_3D.C	Thu Jun 07 13:34:24 2012 -0700
@@ -3,7 +3,7 @@
 
 /* This is written from the perspective of axis==x.  For axis==y, we
    switch i and j and everything works out. */
-void SAMRAI::geom::V_Boundary_Refine::Update_V_3D
+void SAMRAI::geom::Stokes::V_Boundary_Refine::Update_V_3D
 (const int &axis,
  const int &boundary_direction,
  const bool &boundary_positive,
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/V_Boundary_Refine/refine.C
--- a/src/Stokes/V_Boundary_Refine/refine.C	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/V_Boundary_Refine/refine.C	Thu Jun 07 13:34:24 2012 -0700
@@ -13,13 +13,13 @@
 #include "Stokes/set_boundary.h"
 #include "Constants.h"
 
-void SAMRAI::geom::V_Boundary_Refine::refine(
-   hier::Patch& fine,
-   const hier::Patch& coarse,
-   const int dst_component,
-   const int src_component,
-   const hier::BoxOverlap& fine_overlap,
-   const hier::IntVector& ratio) const
+void SAMRAI::geom::Stokes::V_Boundary_Refine::refine
+(hier::Patch& fine,
+ const hier::Patch& coarse,
+ const int dst_component,
+ const int src_component,
+ const hier::BoxOverlap& fine_overlap,
+ const hier::IntVector& ratio) const
 {
    const pdat::SideOverlap* t_overlap =
       dynamic_cast<const pdat::SideOverlap *>(&fine_overlap);
@@ -38,13 +38,14 @@ void SAMRAI::geom::V_Boundary_Refine::re
      }
 }
 
-void SAMRAI::geom::V_Boundary_Refine::refine(hier::Patch& fine,
-                                             const hier::Patch& coarse,
-                                             const int dst_component,
-                                             const int src_component,
-                                             const hier::Box& overlap_box,
-                                             const hier::IntVector& ratio,
-                                             const int &axis) const
+void SAMRAI::geom::Stokes::V_Boundary_Refine::refine
+(hier::Patch& fine,
+ const hier::Patch& coarse,
+ const int dst_component,
+ const int src_component,
+ const hier::Box& overlap_box,
+ const hier::IntVector& ratio,
+ const int &axis) const
 {
    const tbox::Dimension& dimension(getDim());
    TBOX_DIM_ASSERT_CHECK_DIM_ARGS4(dimension, fine, coarse, overlap_box, ratio);
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/V_Coarsen.h
--- a/src/Stokes/V_Coarsen.h	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/V_Coarsen.h	Thu Jun 07 13:34:24 2012 -0700
@@ -9,8 +9,8 @@
  *
  ************************************************************************/
 
-#ifndef included_geom_V_Coarsen
-#define included_geom_V_Coarsen
+#ifndef GAMRA_STOKES_V_COARSEN_H
+#define GAMRA_STOKES_V_COARSEN_H
 
 #include "SAMRAI/SAMRAI_config.h"
 
@@ -25,6 +25,7 @@
 
 namespace SAMRAI {
 namespace geom {
+namespace Stokes {
 
 /**
  * Class V_Coarsen implements averaging 
@@ -144,4 +145,5 @@ private:
 
 }
 }
+}
 #endif
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/V_Coarsen/coarsen_2D.C
--- a/src/Stokes/V_Coarsen/coarsen_2D.C	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/V_Coarsen/coarsen_2D.C	Thu Jun 07 13:34:24 2012 -0700
@@ -8,9 +8,6 @@
  *                a Cartesian mesh. 
  *
  ************************************************************************/
-
-#ifndef included_geom_V_Coarsen_C
-#define included_geom_V_Coarsen_C
 
 #include "Stokes/V_Coarsen.h"
 
@@ -37,12 +34,13 @@ inline void coarsen_point_2D(const pdat:
 }
 
 
-void SAMRAI::geom::V_Coarsen::coarsen_2D(hier::Patch& coarse,
-                                         const hier::Patch& fine,
-                                         const int dst_component,
-                                         const int src_component,
-                                         const hier::Box& coarse_box,
-                                         const hier::IntVector& ratio) const
+void SAMRAI::geom::Stokes::V_Coarsen::coarsen_2D
+(hier::Patch& coarse,
+ const hier::Patch& fine,
+ const int dst_component,
+ const int src_component,
+ const hier::Box& coarse_box,
+ const hier::IntVector& ratio) const
 {
   const tbox::Dimension& dim(getDim());
 
@@ -143,5 +141,3 @@ void SAMRAI::geom::V_Coarsen::coarsen_2D
           }
       }
 }
-
-#endif
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/V_Coarsen/coarsen_3D.C
--- a/src/Stokes/V_Coarsen/coarsen_3D.C	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/V_Coarsen/coarsen_3D.C	Thu Jun 07 13:34:24 2012 -0700
@@ -8,9 +8,6 @@
  *                a Cartesian mesh. 
  *
  ************************************************************************/
-
-#ifndef included_geom_V_Coarsen_C
-#define included_geom_V_Coarsen_C
 
 #include "Stokes/V_Coarsen.h"
 
@@ -41,12 +38,13 @@ inline void coarsen_point_3D(const pdat:
 }
 
 
-void SAMRAI::geom::V_Coarsen::coarsen_3D(hier::Patch& coarse,
-                                         const hier::Patch& fine,
-                                         const int dst_component,
-                                         const int src_component,
-                                         const hier::Box& coarse_box,
-                                         const hier::IntVector& ratio) const
+void SAMRAI::geom::Stokes::V_Coarsen::coarsen_3D
+(hier::Patch& coarse,
+ const hier::Patch& fine,
+ const int dst_component,
+ const int src_component,
+ const hier::Box& coarse_box,
+ const hier::IntVector& ratio) const
 {
   const tbox::Dimension& dim(getDim());
 
@@ -195,5 +193,3 @@ void SAMRAI::geom::V_Coarsen::coarsen_3D
             }
         }
 }
-
-#endif
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/V_Coarsen_Patch_Strategy.h
--- a/src/Stokes/V_Coarsen_Patch_Strategy.h	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/V_Coarsen_Patch_Strategy.h	Thu Jun 07 13:34:24 2012 -0700
@@ -7,8 +7,8 @@
  * Description:   Robin boundary condition support on cartesian grids. 
  *
  ************************************************************************/
-#ifndef included_solv_V_Coarsen_Patch_Strategy
-#define included_solv_V_Coarsen_Patch_Strategy
+#ifndef GAMRA_STOKES_V_COARSEN_PATCH_STRATEGY_H
+#define GAMRA_STOKES_V_COARSEN_PATCH_STRATEGY_H
 
 #include "SAMRAI/SAMRAI_config.h"
 
@@ -22,6 +22,7 @@
 
 namespace SAMRAI {
 namespace solv {
+namespace Stokes {
 
 /*!
  * @brief Helper utility for setting boundary conditions on V.
@@ -410,5 +411,6 @@ private:
 
 }
 }
+}
 
 #endif  // included_solv_V_Coarsen_Patch_Strategy
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/V_Coarsen_Patch_Strategy/postprocessCoarsen_2D.C
--- a/src/Stokes/V_Coarsen_Patch_Strategy/postprocessCoarsen_2D.C	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/V_Coarsen_Patch_Strategy/postprocessCoarsen_2D.C	Thu Jun 07 13:34:24 2012 -0700
@@ -1,7 +1,7 @@
 #include "Stokes/V_Coarsen_Patch_Strategy.h"
 
 void
-SAMRAI::solv::V_Coarsen_Patch_Strategy::postprocessCoarsen_2D
+SAMRAI::solv::Stokes::V_Coarsen_Patch_Strategy::postprocessCoarsen_2D
 (hier::Patch& coarse,
  const hier::Patch& fine,
  const hier::Box& ,
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/V_Coarsen_Patch_Strategy/postprocessCoarsen_3D.C
--- a/src/Stokes/V_Coarsen_Patch_Strategy/postprocessCoarsen_3D.C	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/V_Coarsen_Patch_Strategy/postprocessCoarsen_3D.C	Thu Jun 07 13:34:24 2012 -0700
@@ -1,7 +1,7 @@
 #include "Stokes/V_Coarsen_Patch_Strategy.h"
 
 void
-SAMRAI::solv::V_Coarsen_Patch_Strategy::postprocessCoarsen_3D
+SAMRAI::solv::Stokes::V_Coarsen_Patch_Strategy::postprocessCoarsen_3D
 (hier::Patch& coarse,
  const hier::Patch& fine,
  const hier::Box& ,
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/V_Refine.C
--- a/src/Stokes/V_Refine.C	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/V_Refine.C	Thu Jun 07 13:34:24 2012 -0700
@@ -8,9 +8,6 @@
  *                a Cartesian mesh. 
  *
  ************************************************************************/
-
-#ifndef included_geom_V_Refine_C
-#define included_geom_V_Refine_C
 
 #include "V_Refine.h"
 
@@ -23,136 +20,134 @@
 #include "SAMRAI/tbox/Utilities.h"
 #include "SAMRAI/pdat/CellData.h"
 
-void SAMRAI::geom::V_Refine::refine(
-   hier::Patch& fine,
-   const hier::Patch& coarse,
-   const int dst_component,
-   const int src_component,
-   const hier::BoxOverlap& fine_overlap,
-   const hier::IntVector& ratio) const
+void SAMRAI::geom::Stokes::V_Refine::refine(hier::Patch& fine,
+                                            const hier::Patch& coarse,
+                                            const int dst_component,
+                                            const int src_component,
+                                            const hier::BoxOverlap& fine_overlap,
+                                            const hier::IntVector& ratio) const
 {
-   const pdat::SideOverlap* t_overlap =
-      dynamic_cast<const pdat::SideOverlap *>(&fine_overlap);
+  const pdat::SideOverlap* t_overlap =
+    dynamic_cast<const pdat::SideOverlap *>(&fine_overlap);
 
-   TBOX_ASSERT(t_overlap != NULL);
+  TBOX_ASSERT(t_overlap != NULL);
 
-   for(int axis=0; axis<getDim().getValue(); ++axis)
-     {
-       const hier::BoxList& boxes = t_overlap->getDestinationBoxList(axis);
-       for (hier::BoxList::Iterator b(boxes); b; b++)
-         {
-           refine(fine,coarse,dst_component,src_component,b(),ratio,axis);
-         }
-     }
+  for(int axis=0; axis<getDim().getValue(); ++axis)
+    {
+      const hier::BoxList& boxes = t_overlap->getDestinationBoxList(axis);
+      for (hier::BoxList::Iterator b(boxes); b; b++)
+        {
+          refine(fine,coarse,dst_component,src_component,b(),ratio,axis);
+        }
+    }
 }
 
-void SAMRAI::geom::V_Refine::refine(hier::Patch& fine,
-                                    const hier::Patch& coarse,
-                                    const int dst_component,
-                                    const int src_component,
-                                    const hier::Box& fine_box,
-                                    const hier::IntVector& ratio,
-                                    const int &axis) const
+void SAMRAI::geom::Stokes::V_Refine::refine(hier::Patch& fine,
+                                            const hier::Patch& coarse,
+                                            const int dst_component,
+                                            const int src_component,
+                                            const hier::Box& fine_box,
+                                            const hier::IntVector& ratio,
+                                            const int &axis) const
 {
-   const tbox::Dimension& dimension(getDim());
-   const int dim(dimension.getValue());
-   TBOX_DIM_ASSERT_CHECK_DIM_ARGS4(dimension, fine, coarse, fine_box, ratio);
+  const tbox::Dimension& dimension(getDim());
+  const int dim(dimension.getValue());
+  TBOX_DIM_ASSERT_CHECK_DIM_ARGS4(dimension, fine, coarse, fine_box, ratio);
 
-   tbox::Pointer<pdat::SideData<double> >
-   v_ptr = coarse.getPatchData(src_component);
-   pdat::SideData<double> &v(*v_ptr);
-   tbox::Pointer<pdat::SideData<double> >
-   v_fine_ptr = fine.getPatchData(dst_component);
-   pdat::SideData<double> &v_fine(*v_fine_ptr);
+  tbox::Pointer<pdat::SideData<double> >
+    v_ptr = coarse.getPatchData(src_component);
+  pdat::SideData<double> &v(*v_ptr);
+  tbox::Pointer<pdat::SideData<double> >
+    v_fine_ptr = fine.getPatchData(dst_component);
+  pdat::SideData<double> &v_fine(*v_fine_ptr);
 
 #ifdef DEBUG_CHECK_ASSERTIONS
-   TBOX_ASSERT(!v_ptr.isNull());
-   TBOX_ASSERT(!v_fine_ptr.isNull());
-   TBOX_ASSERT(v.getDepth() == v_fine.getDepth());
-   TBOX_ASSERT(v.getDepth() == 1);
+  TBOX_ASSERT(!v_ptr.isNull());
+  TBOX_ASSERT(!v_fine_ptr.isNull());
+  TBOX_ASSERT(v.getDepth() == v_fine.getDepth());
+  TBOX_ASSERT(v.getDepth() == 1);
 #endif
 
-   hier::Box coarse_box=coarse.getBox();
-   tbox::Pointer<geom::CartesianPatchGeometry>
-     geom = coarse.getPatchGeometry();
+  hier::Box coarse_box=coarse.getBox();
+  tbox::Pointer<geom::CartesianPatchGeometry>
+    geom = coarse.getPatchGeometry();
 
-   hier::Index ip(hier::Index::getZeroIndex(dimension)), jp(ip), kp(ip);
-   ip[0]=1;
-   jp[1]=1;
-   if(dim>2)
-     kp[2]=1;
-   hier::Index pp[]={ip,jp,kp};
+  hier::Index ip(hier::Index::getZeroIndex(dimension)), jp(ip), kp(ip);
+  ip[0]=1;
+  jp[1]=1;
+  if(dim>2)
+    kp[2]=1;
+  hier::Index pp[]={ip,jp,kp};
 
-   for(pdat::CellIterator ci(fine_box); ci; ci++)
-     {
-       pdat::SideIndex fine(*ci,axis,pdat::SideIndex::Lower);
+  for(pdat::CellIterator ci(fine_box); ci; ci++)
+    {
+      pdat::SideIndex fine(*ci,axis,pdat::SideIndex::Lower);
 
-       pdat::SideIndex center(fine);
-       center.coarsen(hier::Index::getOneIndex(dimension)*2);
+      pdat::SideIndex center(fine);
+      center.coarsen(hier::Index::getOneIndex(dimension)*2);
 
-       /* This assumes that the levels are always properly nested, so
-          that we always have an extra grid space for interpolation.
-          So we only have to have a special case for physical
-          boundaries, where we do not have an extra grid space. */
+      /* This assumes that the levels are always properly nested, so
+         that we always have an extra grid space for interpolation.
+         So we only have to have a special case for physical
+         boundaries, where we do not have an extra grid space. */
 
-       double dvx_dy;
+      double dvx_dy;
 
-       if(fine[axis]%2==0)
-         {
-           /* Maybe this has to be fixed when dvx/dy != 0 on the
-              outer boundary because the approximation to the
-              derivative is not accurate enough? */
+      if(fine[axis]%2==0)
+        {
+          /* Maybe this has to be fixed when dvx/dy != 0 on the
+             outer boundary because the approximation to the
+             derivative is not accurate enough? */
 
-           /* Maybe in 3D we should include cross derivatives? */
+          /* Maybe in 3D we should include cross derivatives? */
 
-           v_fine(fine)=v(center);
+          v_fine(fine)=v(center);
 
-           for(int d=(axis+1)%dim;d!=axis;d=(d+1)%dim)
-             {
-               if(center[d]==coarse_box.lower(d)
-                  && geom->getTouchesRegularBoundary(d,0))
-                 {
-                   dvx_dy=(v(center+pp[d])-v(center))/4;
-                 }
-               else if(center[d]==coarse_box.upper(d)
-                       && geom->getTouchesRegularBoundary(d,1))
-                 {
-                   dvx_dy=(v(center)-v(center-pp[d]))/4;
-                 }
-               else
-                 {
-                   dvx_dy=(v(center+pp[d])-v(center-pp[d]))/8;
-                 }
-               v_fine(fine)+=((fine[d]%2==0) ? (-dvx_dy) : dvx_dy);
-             }
-         }
-       else
-         {
-           v_fine(fine)=(v(center) + v(center+pp[axis]))/2;
+          for(int d=(axis+1)%dim;d!=axis;d=(d+1)%dim)
+            {
+              if(center[d]==coarse_box.lower(d)
+                 && geom->getTouchesRegularBoundary(d,0))
+                {
+                  dvx_dy=(v(center+pp[d])-v(center))/4;
+                }
+              else if(center[d]==coarse_box.upper(d)
+                      && geom->getTouchesRegularBoundary(d,1))
+                {
+                  dvx_dy=(v(center)-v(center-pp[d]))/4;
+                }
+              else
+                {
+                  dvx_dy=(v(center+pp[d])-v(center-pp[d]))/8;
+                }
+              v_fine(fine)+=((fine[d]%2==0) ? (-dvx_dy) : dvx_dy);
+            }
+        }
+      else
+        {
+          v_fine(fine)=(v(center) + v(center+pp[axis]))/2;
 
-           for(int d=(axis+1)%dim;d!=axis;d=(d+1)%dim)
-             {
-               if(center[d]==coarse_box.lower(d)
-                  && geom->getTouchesRegularBoundary(d,0))
-                 {
-                   dvx_dy=(v(center+pp[d])-v(center)
-                           + v(center+pp[d]+pp[axis])-v(center+pp[axis]))/8;
-                 }
-               else if(center[d]==coarse_box.upper(d)
-                       && geom->getTouchesRegularBoundary(d,1))
-                 {
-                   dvx_dy=(v(center)-v(center-pp[d])
-                           + v(center+pp[axis])-v(center-pp[d]+pp[axis]))/8;
-                 }
-               else
-                 {
-                   dvx_dy=
-                     (v(center+pp[d])-v(center-pp[d])
-                      + v(center+pp[d]+pp[axis])-v(center-pp[d]+pp[axis]))/16;
-                 }
-               v_fine(fine)+=((fine[d]%2==0) ? (-dvx_dy) : dvx_dy);
-             }
-         }
-     }
+          for(int d=(axis+1)%dim;d!=axis;d=(d+1)%dim)
+            {
+              if(center[d]==coarse_box.lower(d)
+                 && geom->getTouchesRegularBoundary(d,0))
+                {
+                  dvx_dy=(v(center+pp[d])-v(center)
+                          + v(center+pp[d]+pp[axis])-v(center+pp[axis]))/8;
+                }
+              else if(center[d]==coarse_box.upper(d)
+                      && geom->getTouchesRegularBoundary(d,1))
+                {
+                  dvx_dy=(v(center)-v(center-pp[d])
+                          + v(center+pp[axis])-v(center-pp[d]+pp[axis]))/8;
+                }
+              else
+                {
+                  dvx_dy=
+                    (v(center+pp[d])-v(center-pp[d])
+                     + v(center+pp[d]+pp[axis])-v(center-pp[d]+pp[axis]))/16;
+                }
+              v_fine(fine)+=((fine[d]%2==0) ? (-dvx_dy) : dvx_dy);
+            }
+        }
+    }
 }
-#endif
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/V_Refine.h
--- a/src/Stokes/V_Refine.h	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/V_Refine.h	Thu Jun 07 13:34:24 2012 -0700
@@ -9,8 +9,8 @@
  *
  ************************************************************************/
 
-#ifndef included_geom_V_Refine
-#define included_geom_V_Refine
+#ifndef GAMRA_STOKES_V_REFINE_H
+#define GAMRA_STOKES_V_REFINE_H
 
 #include "SAMRAI/SAMRAI_config.h"
 
@@ -25,6 +25,7 @@
 
 namespace SAMRAI {
 namespace geom {
+namespace Stokes {
 
 /**
  * Class V_Refine implements linear
@@ -140,4 +141,5 @@ private:
 
 }
 }
+}
 #endif
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/V_Refine_Patch_Strategy.h
--- a/src/Stokes/V_Refine_Patch_Strategy.h	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/V_Refine_Patch_Strategy.h	Thu Jun 07 13:34:24 2012 -0700
@@ -7,8 +7,8 @@
  * Description:   Robin boundary condition support on cartesian grids. 
  *
  ************************************************************************/
-#ifndef included_solv_V_Refine_Patch_Strategy
-#define included_solv_V_Refine_Patch_Strategy
+#ifndef GAMRA_STOKES_V_REFINE_PATCH_STRATEGY_H
+#define GAMRA_STOKES_V_REFINE_PATCH_STRATEGY_H
 
 #include "SAMRAI/SAMRAI_config.h"
 
@@ -21,6 +21,7 @@
 
 namespace SAMRAI {
 namespace solv {
+namespace Stokes {
 
 /*!
  * @brief Helper utility for setting boundary conditions on V.
@@ -404,5 +405,6 @@ private:
 
 }
 }
+}
 
 #endif  // included_solv_V_Refine_Patch_Strategy
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/dRc_dp.h
--- a/src/Stokes/dRc_dp.h	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/dRc_dp.h	Thu Jun 07 13:34:24 2012 -0700
@@ -1,5 +1,5 @@
-#ifndef GAMR_DRC_DP
-#define GAMR_DRC_DP
+#ifndef GAMR_STOKES_DRC_DP_H
+#define GAMR_STOKES_DRC_DP_H
 
 #include "SAMRAI/pdat/CellData.h"
 #include "SAMRAI/pdat/NodeData.h"
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/dRm_dv.h
--- a/src/Stokes/dRm_dv.h	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/dRm_dv.h	Thu Jun 07 13:34:24 2012 -0700
@@ -1,5 +1,5 @@
-#ifndef GAMR_DRM_DV
-#define GAMR_DRM_DV
+#ifndef GAMR_STOKES_DRM_DV_H
+#define GAMR_STOKES_DRM_DV_H
 
 #include "SAMRAI/pdat/CellData.h"
 #include "SAMRAI/pdat/EdgeData.h"
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/set_boundary.h
--- a/src/Stokes/set_boundary.h	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/set_boundary.h	Thu Jun 07 13:34:24 2012 -0700
@@ -1,5 +1,5 @@
-#ifndef SET_V_BOUNDARY_H
-#define SET_V_BOUNDARY_H
+#ifndef GAMRA_STOKES_SET_BOUNDARY_H
+#define GAMRA_STOKES_SET_BOUNDARY_H
 
 #include "SAMRAI/hier/Patch.h"
 
diff -r 2816cd6f8030 -r c77b196abc8c src/Stokes/viscosity_coarsen.h
--- a/src/Stokes/viscosity_coarsen.h	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/Stokes/viscosity_coarsen.h	Thu Jun 07 13:34:24 2012 -0700
@@ -1,5 +1,5 @@
-#ifndef GAMR_VISCOSITY_COARSEN_H
-#define GAMR_VISCOSITY_COARSEN_H
+#ifndef GAMR_STOKES_VISCOSITY_COARSEN_H
+#define GAMR_STOKES_VISCOSITY_COARSEN_H
 
 /* This uses both the cell-centered and node-centered viscosities to
    coarsen the viscosity.  In 2D, if you rotate the grid 45 degrees,
diff -r 2816cd6f8030 -r c77b196abc8c src/main.C
--- a/src/main.C	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/main.C	Thu Jun 07 13:34:24 2012 -0700
@@ -4,7 +4,7 @@
  * information, see COPYRIGHT and COPYING.LESSER. 
  *
  * Copyright:     (c) 1997-2010 Lawrence Livermore National Security, LLC
- * Description:   Main program for FAC Stokes example 
+ * Description:   Main program
  *
  ************************************************************************/
 #include "SAMRAI/SAMRAI_config.h"
@@ -35,8 +35,17 @@ using namespace std;
 #include "Stokes/V_Boundary_Refine.h"
 #include "Stokes/V_Coarsen.h"
 #include "Stokes/Resid_Coarsen.h"
+#include "Elastic/P_Refine.h"
+#include "Elastic/V_Refine.h"
+#include "Elastic/P_Boundary_Refine.h"
+#include "Elastic/V_Boundary_Refine.h"
+#include "Elastic/V_Coarsen.h"
+#include "Elastic/Resid_Coarsen.h"
 
 #include "Stokes/FAC.h"
+#include "Elastic/FAC.h"
+
+#include "solve_system.h"
 
 using namespace SAMRAI;
 
@@ -44,20 +53,20 @@ using namespace SAMRAI;
 ************************************************************************
 *                                                                      *
 * This is the driver program to demonstrate                            *
-* how to use the FAC Stokes solver.                                   *
+* how to use the Stokes and Elastic FAC solver.                                   *
 *                                                                      *
 * We set up the simple problem                                         *
 *          u + div(grad(u)) = sin(x)*sin(y)                            *
 * in the domain [0:1]x[0:1], with u=0 on the                           *
 * boundary.                                                            *
 *                                                                      *
-* Stokes::FAC is the primary object used to                             *
+* Stokes::FAC and Elastic::FAC are the primary objects used to         *
 * set up and solve the system.  It maintains                           *
 * the data for the computed solution u, the                            *
 * exact solution, and the right hand side.                             *
 *                                                                      *
 * The hierarchy created to solve this problem                          *
-* has only one level.  (The FAC Stokes solver                         *
+* has only one level.  (The Stokes::FAC and Elastic::FAC solver        *
 * is a single-level solver.)                                           *
 *                                                                      *
 *************************************************************************
@@ -149,188 +158,84 @@ int main(
      * for this application, see comments at top of file.
      */
 
-    tbox::Pointer<geom::CartesianGridGeometry>
-      grid_geometry(new geom::CartesianGridGeometry
-                    (dim,
-                     base_name + "CartesianGridGeometry",
+    SAMRAI::tbox::Pointer<SAMRAI::geom::CartesianGridGeometry>
+      grid_geometry(new SAMRAI::geom::CartesianGridGeometry
+                    (dim, base_name + "CartesianGridGeometry",
                      input_db->getDatabase("CartesianGridGeometry")));
-    grid_geometry->addSpatialRefineOperator
-      (tbox::Pointer<SAMRAI::xfer::RefineOperator>
-       (new SAMRAI::geom::P_Refine(dim)));
-    grid_geometry->addSpatialRefineOperator
-      (tbox::Pointer<SAMRAI::xfer::RefineOperator>
-       (new SAMRAI::geom::V_Refine(dim)));
-    grid_geometry->addSpatialRefineOperator
-      (tbox::Pointer<SAMRAI::xfer::RefineOperator>
-       (new SAMRAI::geom::P_Boundary_Refine(dim)));
-    grid_geometry->addSpatialRefineOperator
-      (tbox::Pointer<SAMRAI::xfer::RefineOperator>
-       (new SAMRAI::geom::V_Boundary_Refine(dim)));
-    grid_geometry->addSpatialCoarsenOperator
-      (tbox::Pointer<SAMRAI::xfer::CoarsenOperator>
-       (new SAMRAI::geom::V_Coarsen(dim)));
 
-    tbox::Pointer<hier::PatchHierarchy>
-      patch_hierarchy(new hier::PatchHierarchy
+    SAMRAI::tbox::Pointer<SAMRAI::hier::PatchHierarchy>
+      patch_hierarchy(new SAMRAI::hier::PatchHierarchy
                       (base_name + "::PatchHierarchy",
                        grid_geometry,
                        input_db->getDatabase("PatchHierarchy")));
 
     /*
-     * The Stokes::FAC object is the main user object specific to the
-     * problem being solved.  It provides the implementations for setting
-     * up the grid and plotting data.  It also wraps up the solve
-     * process that includes making the initial guess, specifying the
-     * boundary conditions and call the solver.
+     * The Stokes::FAC and Elastic::FAC objects is the main user
+     * object specific to the problem being solved.  It provides the
+     * implementations for setting up the grid and plotting data.  It
+     * also wraps up the solve process that includes making the
+     * initial guess, specifying the boundary conditions and call the
+     * solver.
      */
-    Stokes::FAC fac_stokes(base_name + "::Stokes::FAC",
-                           dim,
-                           input_db->isDatabase("Stokes") ?
-                           input_db->getDatabase("Stokes") :
-                           tbox::Pointer<tbox::Database>(NULL));
 
-    grid_geometry->addSpatialCoarsenOperator
-      (tbox::Pointer<SAMRAI::xfer::CoarsenOperator>
-       (new SAMRAI::geom::Stokes::Resid_Coarsen(dim,fac_stokes.cell_viscosity_id)));
+    if(input_db->isDatabase("Stokes"))
+      {
+        Stokes::FAC fac_stokes(base_name + "::Stokes::FAC", dim,
+                               input_db->getDatabase("Stokes"));
+        grid_geometry->addSpatialRefineOperator
+          (SAMRAI::tbox::Pointer<SAMRAI::xfer::RefineOperator>
+           (new SAMRAI::geom::Stokes::P_Refine(dim)));
+        grid_geometry->addSpatialRefineOperator
+          (SAMRAI::tbox::Pointer<SAMRAI::xfer::RefineOperator>
+           (new SAMRAI::geom::Stokes::V_Refine(dim)));
+        grid_geometry->addSpatialRefineOperator
+          (SAMRAI::tbox::Pointer<SAMRAI::xfer::RefineOperator>
+           (new SAMRAI::geom::Stokes::P_Boundary_Refine(dim)));
+        grid_geometry->addSpatialRefineOperator
+          (SAMRAI::tbox::Pointer<SAMRAI::xfer::RefineOperator>
+           (new SAMRAI::geom::Stokes::V_Boundary_Refine(dim)));
+        grid_geometry->addSpatialCoarsenOperator
+          (SAMRAI::tbox::Pointer<SAMRAI::xfer::CoarsenOperator>
+           (new SAMRAI::geom::Stokes::V_Coarsen(dim)));
+        grid_geometry->addSpatialCoarsenOperator
+          (SAMRAI::tbox::Pointer<SAMRAI::xfer::CoarsenOperator>
+           (new SAMRAI::geom::Stokes::Resid_Coarsen(dim,fac_stokes.cell_viscosity_id)));
 
-    /*
-     * Create the tag-and-initializer, box-generator and load-balancer
-     * object references required by the gridding_algorithm object.
-     */
-    tbox::Pointer<mesh::StandardTagAndInitialize>
-      tag_and_initializer(new mesh::StandardTagAndInitialize
-                          (dim,
-                           "CellTaggingMethod",
-                           tbox::Pointer<mesh::StandardTagAndInitStrategy>
-                           (&fac_stokes, false),
-                           input_db->getDatabase("StandardTagAndInitialize")
-                           ));
-    tbox::Pointer<mesh::BergerRigoutsos>
-      box_generator(new mesh::BergerRigoutsos(dim));
-    tbox::Pointer<mesh::TreeLoadBalancer>
-      load_balancer(new mesh::TreeLoadBalancer
-                    (dim,
-                     "load balancer",
-                     tbox::Pointer<tbox::Database>()));
-    load_balancer->setSAMRAI_MPI(SAMRAI::tbox::SAMRAI_MPI::getSAMRAIWorld());
+        solve_system(fac_stokes,main_db,input_db,patch_hierarchy,
+                     base_name,dim);
+      }
+    else
+      {
+        Elastic::FAC fac_elastic(base_name + "::Elastic::FAC", dim,
+                                 input_db->getDatabase("Elastic"));
+        grid_geometry->addSpatialRefineOperator
+          (SAMRAI::tbox::Pointer<SAMRAI::xfer::RefineOperator>
+           (new SAMRAI::geom::Elastic::P_Refine(dim)));
+        grid_geometry->addSpatialRefineOperator
+          (SAMRAI::tbox::Pointer<SAMRAI::xfer::RefineOperator>
+           (new SAMRAI::geom::Elastic::V_Refine(dim)));
+        grid_geometry->addSpatialRefineOperator
+          (SAMRAI::tbox::Pointer<SAMRAI::xfer::RefineOperator>
+           (new SAMRAI::geom::Elastic::P_Boundary_Refine(dim)));
+        grid_geometry->addSpatialRefineOperator
+          (SAMRAI::tbox::Pointer<SAMRAI::xfer::RefineOperator>
+           (new SAMRAI::geom::Elastic::V_Boundary_Refine(dim)));
+        grid_geometry->addSpatialCoarsenOperator
+          (SAMRAI::tbox::Pointer<SAMRAI::xfer::CoarsenOperator>
+           (new SAMRAI::geom::Elastic::V_Coarsen(dim)));
+        grid_geometry->addSpatialCoarsenOperator
+          (SAMRAI::tbox::Pointer<SAMRAI::xfer::CoarsenOperator>
+           (new SAMRAI::geom::Elastic::Resid_Coarsen(dim,fac_elastic.cell_moduli_id)));
 
-    /*
-     * Create the gridding algorithm used to generate the SAMR grid
-     * and create the grid.
-     */
-    tbox::Pointer<mesh::GriddingAlgorithm> gridding_algorithm;
-    gridding_algorithm =
-      new mesh::GriddingAlgorithm(patch_hierarchy,
-                                  "Gridding Algorithm",
-                                  input_db->getDatabase("GriddingAlgorithm"),
-                                  tag_and_initializer,
-                                  box_generator,
-                                  load_balancer);
-    // tbox::plog << "Gridding algorithm:" << endl;
-    // gridding_algorithm->printClassData(tbox::plog);
-
-    /*
-     * Make the coarsest patch level where we will be solving.
-     */
-    gridding_algorithm->makeCoarsestLevel(0.0);
-    // bool done = false;
-    // for (int lnum = 0;
-    //      patch_hierarchy->levelCanBeRefined(lnum) && !done; lnum++) {
-    //   tbox::plog << "Adding finner levels with lnum = " << lnum << endl;
-    //   gridding_algorithm->makeFinerLevel(0.0,true,0);
-    //   tbox::plog << "Just added finer levels with lnum = " << lnum << endl;
-    //   done = !(patch_hierarchy->finerLevelExists(lnum));
-    // }
-
-    /*
-     * Set up the plotter for the hierarchy just created.
-     * The Stokes::FAC object handles the data and has the
-     * function setupExternalPlotter to register its data
-     * with the plotter.
-     */
-    tbox::Array<string> vis_writer(1);
-    vis_writer[0] = "Visit";
-    if (main_db->keyExists("vis_writer")) {
-      vis_writer = main_db->getStringArray("vis_writer");
-    }
-    bool use_visit = false;
-    for (int i = 0; i < vis_writer.getSize(); i++) {
-      if (vis_writer[i] == "VisIt") use_visit = true;
-    }
-#ifdef HAVE_HDF5
-    tbox::Pointer<appu::VisItDataWriter> visit_writer;
-    string vis_filename =
-      main_db->getStringWithDefault("vis_filename", base_name);
-    if (use_visit) {
-      visit_writer = new appu::VisItDataWriter(dim,
-                                               "Visit Writer",
-                                               vis_filename + ".visit");
-      fac_stokes.setupPlotter(*visit_writer);
-    }
-#endif
-
-    /*
-     * After creating all objects and initializing their state,
-     * we print the input database and variable database contents
-     * to the log file.
-     */
-    tbox::plog << "\nCheck input data and variables before simulation:"
-               << endl;
-    tbox::plog << "Input database..." << endl;
-    input_db->printClassData(tbox::plog);
-
-    /*
-     * Solve.
-     */
-    fac_stokes.solve();
-
-    bool done(false);
-    for (int lnum = 0;
-         patch_hierarchy->levelCanBeRefined(lnum) && !done; lnum++)
-      {
-            tbox::Array<int> tag_buffer(patch_hierarchy->getMaxNumberOfLevels());
-            for (int ln = 0; ln < tag_buffer.getSize(); ++ln) {
-               tag_buffer[ln] = 1;
-            }
-            gridding_algorithm->regridAllFinerLevels(
-               0,
-               0.0,
-               tag_buffer);
-            tbox::plog << "Newly adapted hierarchy\n";
-
-
-      // tbox::plog << "Adding finner levels with lnum = " << lnum << endl;
-      // gridding_algorithm->makeFinerLevel(0.0,true,0);
-      // tbox::plog << "Just added finer levels with lnum = " << lnum << endl;
-      done = !(patch_hierarchy->finerLevelExists(lnum));
-      fac_stokes.solve();
-    }
-    // {
-    //     tbox::Array<int> tag_buffer(patch_hierarchy->getMaxNumberOfLevels());
-    //     for (int ln = 0; ln < tag_buffer.getSize(); ++ln) {
-    //       tag_buffer[ln] = 1;
-    //     }
-    //     gridding_algorithm->regridAllFinerLevels(
-    //                                              0,
-    //                                              0.0,
-    //                                              tag_buffer);
-    // }
-#ifdef HAVE_HDF5
-    /*
-     * Plot.
-     */
-    if (use_visit) {
-      visit_writer->writePlotData(patch_hierarchy, 0);
-    }
-#endif
+        solve_system(fac_elastic,main_db,input_db,patch_hierarchy,
+                     base_name,dim);
+      }
 
     /*
      * Deallocate objects when done.
      */
 
-    tbox::TimerManager::getManager()->print(tbox::plog);
   }
-
   /*
    * This print is for the SAMRAI testing framework.  Passing here
    * means application ran.  A better test would actually test the
diff -r 2816cd6f8030 -r c77b196abc8c src/quad_offset_interpolate.h
--- a/src/quad_offset_interpolate.h	Wed Jun 06 07:43:07 2012 -0700
+++ b/src/quad_offset_interpolate.h	Thu Jun 07 13:34:24 2012 -0700
@@ -1,5 +1,5 @@
-#ifndef QUAD_OFFSET_INTERPOLATE_H
-#define QUAD_OFFSET_INTERPOLATE_H
+#ifndef GAMRA_QUAD_OFFSET_INTERPOLATE_H
+#define GAMRA_QUAD_OFFSET_INTERPOLATE_H
 
 /* Interpolate up to quadratic order from three coarse points (C) to
    two fine points (f) with the setup
diff -r 2816cd6f8030 -r c77b196abc8c src/solve_system.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/solve_system.h	Thu Jun 07 13:34:24 2012 -0700
@@ -0,0 +1,149 @@
+#ifndef GAMRA_SOLVE_SYSTEM_H
+#define GAMRA_SOLVE_SYSTEM_H
+
+template<class T>
+void solve_system(T &fac,
+                  SAMRAI::tbox::Pointer<SAMRAI::tbox::Database> &main_db,
+                  SAMRAI::tbox::Pointer<SAMRAI::tbox::Database> &input_db,
+                  SAMRAI::tbox::Pointer<SAMRAI::hier::PatchHierarchy> &patch_hierarchy,
+                  const string &base_name,
+                  const SAMRAI::tbox::Dimension &dim)
+{
+
+  /*
+   * Create the tag-and-initializer, box-generator and load-balancer
+   * object references required by the gridding_algorithm object.
+   */
+  SAMRAI::tbox::Pointer<SAMRAI::mesh::StandardTagAndInitialize>
+    tag_and_initializer(new SAMRAI::mesh::StandardTagAndInitialize
+                        (dim,
+                         "CellTaggingMethod",
+                         SAMRAI::tbox::Pointer<SAMRAI::mesh::StandardTagAndInitStrategy>
+                         (&fac, false),
+                         input_db->getDatabase("StandardTagAndInitialize")
+                         ));
+
+  SAMRAI::tbox::Pointer<SAMRAI::mesh::BergerRigoutsos>
+    box_generator(new SAMRAI::mesh::BergerRigoutsos(dim));
+  SAMRAI::tbox::Pointer<SAMRAI::mesh::TreeLoadBalancer>
+    load_balancer(new SAMRAI::mesh::TreeLoadBalancer
+                  (dim,
+                   "load balancer",
+                   SAMRAI::tbox::Pointer<SAMRAI::tbox::Database>()));
+  load_balancer->setSAMRAI_MPI(SAMRAI::tbox::SAMRAI_MPI::getSAMRAIWorld());
+
+  /*
+   * Create the gridding algorithm used to generate the SAMR grid
+   * and create the grid.
+   */
+  SAMRAI::tbox::Pointer<SAMRAI::mesh::GriddingAlgorithm> gridding_algorithm;
+  gridding_algorithm =
+    new SAMRAI::mesh::GriddingAlgorithm(patch_hierarchy,
+                                        "Gridding Algorithm",
+                                        input_db->getDatabase("GriddingAlgorithm"),
+                                        tag_and_initializer,
+                                        box_generator,
+                                        load_balancer);
+  // SAMRAI::tbox::plog << "Gridding algorithm:" << endl;
+  // gridding_algorithm->printClassData(SAMRAI::tbox::plog);
+
+  /*
+   * Make the coarsest patch level where we will be solving.
+   */
+  gridding_algorithm->makeCoarsestLevel(0.0);
+  // bool done = false;
+  // for (int lnum = 0;
+  //      patch_hierarchy->levelCanBeRefined(lnum) && !done; lnum++) {
+  //   SAMRAI::tbox::plog << "Adding finner levels with lnum = " << lnum << endl;
+  //   gridding_algorithm->makeFinerLevel(0.0,true,0);
+  //   SAMRAI::tbox::plog << "Just added finer levels with lnum = " << lnum << endl;
+  //   done = !(patch_hierarchy->finerLevelExists(lnum));
+  // }
+
+  /*
+   * Set up the plotter for the hierarchy just created.  The FAC
+   * object handles the data and has the function
+   * setupExternalPlotter to register its data with the plotter.
+   */
+  SAMRAI::tbox::Array<string> vis_writer(1);
+  vis_writer[0] = "Visit";
+  if (main_db->keyExists("vis_writer")) {
+    vis_writer = main_db->getStringArray("vis_writer");
+  }
+  bool use_visit = false;
+  for (int i = 0; i < vis_writer.getSize(); i++) {
+    if (vis_writer[i] == "VisIt") use_visit = true;
+  }
+#ifdef HAVE_HDF5
+  SAMRAI::tbox::Pointer<SAMRAI::appu::VisItDataWriter> visit_writer;
+  string vis_filename =
+    main_db->getStringWithDefault("vis_filename", base_name);
+  if (use_visit) {
+    visit_writer = new SAMRAI::appu::VisItDataWriter(dim,
+                                                     "Visit Writer",
+                                                     vis_filename + ".visit");
+    fac.setupPlotter(*visit_writer);
+  }
+#endif
+
+  /*
+   * After creating all objects and initializing their state,
+   * we print the input database and variable database contents
+   * to the log file.
+   */
+  SAMRAI::tbox::plog << "\nCheck input data and variables before simulation:"
+                     << endl;
+  SAMRAI::tbox::plog << "Input database..." << endl;
+  input_db->printClassData(SAMRAI::tbox::plog);
+
+  /*
+   * Solve.
+   */
+  fac.solve();
+
+
+  bool done(false);
+  for (int lnum = 0;
+       patch_hierarchy->levelCanBeRefined(lnum) && !done; lnum++)
+    {
+      SAMRAI::tbox::Array<int> tag_buffer(patch_hierarchy->getMaxNumberOfLevels());
+      for (int ln = 0; ln < tag_buffer.getSize(); ++ln) {
+        tag_buffer[ln] = 1;
+      }
+      gridding_algorithm->regridAllFinerLevels(
+                                               0,
+                                               0.0,
+                                               tag_buffer);
+      SAMRAI::tbox::plog << "Newly adapted hierarchy\n";
+
+
+      // SAMRAI::tbox::plog << "Adding finner levels with lnum = " << lnum << endl;
+      // gridding_algorithm->makeFinerLevel(0.0,true,0);
+      // SAMRAI::tbox::plog << "Just added finer levels with lnum = " << lnum << endl;
+      done = !(patch_hierarchy->finerLevelExists(lnum));
+      fac.solve();
+    }
+
+  // {
+  //     SAMRAI::tbox::Array<int> tag_buffer(patch_hierarchy->getMaxNumberOfLevels());
+  //     for (int ln = 0; ln < tag_buffer.getSize(); ++ln) {
+  //       tag_buffer[ln] = 1;
+  //     }
+  //     gridding_algorithm->regridAllFinerLevels(
+  //                                              0,
+  //                                              0.0,
+  //                                              tag_buffer);
+  // }
+#ifdef HAVE_HDF5
+  /*
+   * Plot.
+   */
+  if (use_visit) {
+    visit_writer->writePlotData(patch_hierarchy, 0);
+  }
+#endif
+
+  SAMRAI::tbox::TimerManager::getManager()->print(SAMRAI::tbox::plog);
+}
+
+#endif
diff -r 2816cd6f8030 -r c77b196abc8c wscript
--- a/wscript	Wed Jun 06 07:43:07 2012 -0700
+++ b/wscript	Thu Jun 07 13:34:24 2012 -0700
@@ -7,7 +7,6 @@ def configure(conf):
 def configure(conf):
     conf.load('compiler_cxx')
 def build(bld):
-    # bld.recurse('src/libtcod-1.5.0')
     bld.program(
         features     = ['cxx','cprogram'],
         source       = ['src/main.C',
@@ -72,16 +71,80 @@ def build(bld):
                         'src/Stokes/FACSolver/setBcObject.C',
                         'src/Stokes/FACSolver/setBoundaries.C',
                         'src/Stokes/FACSolver/solveSystem.C',
-                        'src/Stokes/HypreSolver.C'],
+                        'src/Stokes/HypreSolver.C',
+                        'src/Elastic/FAC/FAC.C',
+                        'src/Elastic/FAC/fix_moduli.C',
+                        'src/Elastic/FAC/applyGradientDetector.C',
+                        'src/Elastic/FAC/initializeLevelData.C',
+                        'src/Elastic/FAC/packDerivedDataIntoDoubleBuffer.C',
+                        'src/Elastic/FAC/resetHierarchyConfiguration.C',
+                        'src/Elastic/FAC/setupPlotter.C',
+                        'src/Elastic/FAC/solve.C',
+                        'src/Elastic/P_Refine.C',
+                        'src/Elastic/V_Refine/refine.C',
+                        'src/Elastic/V_Refine/refine_along_line.C',
+                        'src/Elastic/Resid_Coarsen.C',
+                        'src/Elastic/V_Coarsen/coarsen_2D.C',
+                        'src/Elastic/V_Coarsen/coarsen_3D.C',
+                        'src/Elastic/P_Boundary_Refine/refine.C',
+                        'src/Elastic/P_Boundary_Refine/Update_P_2D.C',
+                        'src/Elastic/P_Boundary_Refine/Update_P_3D.C',
+                        'src/Elastic/V_Boundary_Refine/refine.C',
+                        'src/Elastic/V_Boundary_Refine/Update_V_2D.C',
+                        'src/Elastic/V_Boundary_Refine/Update_V_3D.C',
+                        'src/Elastic/V_Coarsen_Patch_Strategy/postprocessCoarsen_2D.C',
+                        'src/Elastic/V_Coarsen_Patch_Strategy/postprocessCoarsen_3D.C',
+                        'src/Elastic/set_boundary.C',
+                        'src/Elastic/FACOps/FACOps.C',
+                        'src/Elastic/FACOps/computeCompositeResidualOnLevel.C',
+                        'src/Elastic/FACOps/residual_2D.C',
+                        'src/Elastic/FACOps/residual_3D.C',
+                        'src/Elastic/FACOps/computeResidualNorm.C',
+                        'src/Elastic/FACOps/computeVectorWeights.C',
+                        'src/Elastic/FACOps/deallocateOperatorState.C',
+                        'src/Elastic/FACOps/finalizeCallback.C',
+                        'src/Elastic/FACOps/initializeOperatorState.C',
+                        'src/Elastic/FACOps/postprocessOneCycle.C',
+                        'src/Elastic/FACOps/prolongErrorAndCorrect.C',
+                        'src/Elastic/FACOps/restrictResidual.C',
+                        'src/Elastic/FACOps/restrictSolution.C',
+                        'src/Elastic/FACOps/smoothError.C',
+                        'src/Elastic/FACOps/smooth_Tackley_2D.C',
+                        'src/Elastic/FACOps/smooth_Tackley_3D.C',
+                        'src/Elastic/FACOps/set_boundaries.C',
+                        'src/Elastic/FACOps/solveCoarsestLevel.C',
+                        'src/Elastic/FACOps/solveCoarsestLevel_HYPRE.C',
+                        'src/Elastic/FACOps/smooth_V_2D.C',
+                        'src/Elastic/FACOps/smooth_V_3D.C',
+                        'src/Elastic/FACOps/xeqScheduleGhostFill.C',
+                        'src/Elastic/FACOps/xeqScheduleGhostFillNoCoarse.C',
+                        'src/Elastic/FACOps/xeqScheduleProlongation.C',
+                        'src/Elastic/FACOps/xeqScheduleRRestriction.C',
+                        'src/Elastic/FACOps/xeqScheduleURestriction.C',
+                        'src/Elastic/FACSolver/FACSolver.C',
+                        'src/Elastic/FACSolver/FACSolver_Destructor.C',
+                        'src/Elastic/FACSolver/createVectorWrappers.C',
+                        'src/Elastic/FACSolver/deallocateSolverState.C',
+                        'src/Elastic/FACSolver/destroyVectorWrappers.C',
+                        'src/Elastic/FACSolver/enableLogging.C',
+                        'src/Elastic/FACSolver/getFromInput.C',
+                        'src/Elastic/FACSolver/initializeSolverState.C',
+                        'src/Elastic/FACSolver/initializeStatics.C',
+                        'src/Elastic/FACSolver/setBcObject.C',
+                        'src/Elastic/FACSolver/setBoundaries.C',
+                        'src/Elastic/FACSolver/solveSystem.C',
+                        'src/Elastic/HypreSolver.C'],
 
         target       = 'gamra',
-        # cxxflags      = ['-std=c++0x','-g','-D_GLIBCXX_DEBUG'],
-        cxxflags      = ['-g', '-Wall', '-Wextra', '-Wconversion',
-                         '-DTESTING=0'],
+        cxxflags      = ['-O3', '-Wall', '-Wextra', '-Wconversion',
+                        '-DTESTING=0', '-Drestrict='],
+        # cxxflags      = ['-g', '-Wall', '-Wextra', '-Wconversion',
+        #                  '-Drestrict='],
         lib          = ['SAMRAI_appu', 'SAMRAI_algs', 'SAMRAI_solv',
                         'SAMRAI_geom', 'SAMRAI_mesh', 'SAMRAI_math',
                         'SAMRAI_pdat', 'SAMRAI_xfer', 'SAMRAI_hier',
-                        'SAMRAI_tbox',   'petsc', 'HYPRE',
+                        'SAMRAI_tbox', 'petsc', 'hdf5',
+                        'HYPRE',
                         'HYPRE_sstruct_ls', 'HYPRE_sstruct_mv',
                         'HYPRE_struct_ls', 'HYPRE_struct_mv',
                         'HYPRE_parcsr_ls',
@@ -92,11 +155,11 @@ def build(bld):
                         'HYPRE_krylov', 'HYPRE_utilities', 'hdf5',
                         'dl', 'm', 'gfortranbegin', 'gfortran', 'm',
                         'gfortranbegin', 'gfortran', 'm', 'gfortranbegin',
-                        'gfortran', 'm', 'sundials_cvode', 'sundials_kinsol'],
-        libpath      = ['../../../SAMRAI-hg-build/lib',
+                        'gfortran', 'm'],
+        libpath      = ['/home/boo/cig/SAMRAI-hg-build/lib',
                         '/usr/lib/petsc/linux-gnu-c-opt/lib'],
-        includes = ['src','../../../SAMRAI-hg-build/include',
-                    '../../../SAMRAI-hg/source',
+        includes = ['src','../FTensor','../../SAMRAI-hg-build/include',
+                    '../../SAMRAI-hg/source',
                     '/usr/lib/petsc/include',
                     '/usr/lib/petsc/bmake/linux-gnu-c-opt',
                     '/usr/lib/petsc/src/vec',



More information about the CIG-COMMITS mailing list