[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 ¢er,
+ 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 ¢er,
+ 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 ¢er,
+ 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 ¢er,
+ 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 ¢er,
+ 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 ¢er,
+ 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 ¢er,
+ 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 ¢er,
+ 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 ¢er,
+ 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 ¢er,
+ const SAMRAI::pdat::CellIndex &left,
+ const E_index &up_e,
+ const E_index ¢er_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 ¢er,
+ const SAMRAI::pdat::CellIndex &left,
+ const SAMRAI::pdat::EdgeIndex &front_y,
+ const SAMRAI::pdat::EdgeIndex ¢er_y,
+ const SAMRAI::pdat::EdgeIndex &up_z,
+ const SAMRAI::pdat::EdgeIndex ¢er_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