[MOAB-dev] commit/MOAB: 35 new changesets

commits-noreply at bitbucket.org commits-noreply at bitbucket.org
Mon Sep 16 17:24:59 CDT 2013


35 new commits in MOAB:

https://bitbucket.org/fathomteam/moab/commits/058563b03d7b/
Changeset:   058563b03d7b
Branch:      None
User:        tautges
Date:        2013-03-13 22:09:45
Summary:     First set of changes from MOABtree repository, from commit b7eea48bccff.

Affected #:  54 files

diff --git a/configure.ac b/configure.ac
index 182b608..057166e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1177,6 +1177,7 @@ AC_CONFIG_FILES([Makefile
                  src/Makefile
                  src/io/Makefile
                  src/io/mhdf/Makefile
+		 src/LocalDiscretization/Makefile
                  src/parallel/Makefile
                  src/oldinc/Makefile
                  test/Makefile

diff --git a/examples/KDTree.cpp b/examples/KDTree.cpp
index f402ca1..584fd82 100644
--- a/examples/KDTree.cpp
+++ b/examples/KDTree.cpp
@@ -76,7 +76,7 @@ int main( )
     // Build a kD-tree from hex elements
   moab::EntityHandle tree_root;
   moab::AdaptiveKDTree tool( &mb );
-  rval = tool.build_tree( elems, tree_root ); CHKERR(rval);
+  rval = tool.build_tree( elems, &tree_root ); CHKERR(rval);
   
     // Loop forever (or until EOF), asking user for a point
     // to query and printing the hex element containing that
@@ -88,7 +88,7 @@ int main( )
       break;
   
     moab::EntityHandle leaf;
-    rval = tool.leaf_containing_point( tree_root, point, leaf ); CHKERR(rval);
+    rval = tool.point_search(point, leaf, NULL,  &tree_root); CHKERR(rval);
     moab::EntityHandle hex = hex_containing_point( mb, leaf, point );
     if (0 == hex) 
       std::cout << "Point is not contained in any hexahedron." << std::endl;

diff --git a/examples/point_in_elem_search.cpp b/examples/point_in_elem_search.cpp
new file mode 100644
index 0000000..3cc16d1
--- /dev/null
+++ b/examples/point_in_elem_search.cpp
@@ -0,0 +1,84 @@
+/** \brief This test shows how to perform local point-in-element searches with MOAB's new tree searching functionality.  
+ *
+ * MOAB's SpatialLocator functionality performs point-in-element searches over a local or parallel mesh.
+ * SpatialLocator is flexible as to what kind of tree is used and what kind of element basis functions are 
+ * used to localize elements and interpolate local fields.
+ */
+
+#include <iostream>
+#include <cstdlib>
+
+#include "moab/Core.hpp"
+#include "moab/Interface.hpp"
+#include "moab/Range.hpp"
+
+using namespace moab;
+
+#define ERR(s) if (MB_SUCCESS != rval) \
+    {std::string str;mb->get_last_error(str); std::cerr << s << str << std::endl; return 1;}
+
+int main(int argc, char **argv) {
+
+  int num_queries = 1000000;
+  
+  if (argc == 1) {
+    std::cout << "Usage: " << argv[0] << "<filename> [num_queries]" << std::endl;
+    return 0;
+  }
+  else if (argc == 3) sscanf(argv[2], "%d", num_queries);
+
+    // instantiate & load a file
+  moab::Interface *mb = new moab::Core();
+
+  Error err;
+  ErrorCode rval = mb->query_interface(err);
+  if (MB_SUCCESS != rval) return 1;
+  
+    // load the file
+  rval = mb->load_file(argv[argc-1]); ERR("Error loading file");
+  
+    // get all 3d elements in the file
+  Range elems;
+  rval = mb->get_entities_by_dimension(0, 3, elems); ERR("Error getting 3d elements");
+  
+    // create a tree to use for the location service
+  AdaptiveKDTree tree(mb);
+
+    // specify an evaluator based on linear hexes
+  ElemEvaluator el_eval(mb, LinearHex::get_eval_set());
+
+    // build the SpatialLocator
+  SpatialLocator sl(mb, elems, &tree, &el_eval);
+  
+    // get the box extents
+  CartVect box_min, box_max, box_extents, pos;
+  rval = sl.get_bounding_box(box_min, box_max); ERR("Problem getting tree bounding box");
+  box_extents = box_max - box_min;
+  
+    // query at random places in the tree
+  EntityHandle elem;
+  CartVect params;
+  bool is_inside;
+  int num_inside = 0;
+  for (int i = 0; i < num_queries; i++) {
+    pos = box_min + 
+        CartVect(box_extents[0]*.01*(rand()%100), box_extents[1]*.01*(rand()%100), box_extents[2]*.01*(rand()%100));
+    
+    ErrorCode tmp_rval = sl.locate_point(pos, tol, in_elem, params, &is_inside);
+    if (MB_SUCCESS != tmp_rval) rval = tmp_rval;
+    if (is_inside) num_inside++;
+  }
+  
+  std::cout << "Mesh contains " << elems.size() << " elements of type " 
+            << CN::EntityTypeName(mb->type_from_handle(*elems.begin())) << std::endl;
+  std::cout << "Bounding box min-max = (" << box_min[0] << "," << box_min[1] << "," << box_min[2] << ")-("
+            << box_max[0] << "," << box_max[1] << "," << box_max[2] << ")" << std::endl;
+  std::cout << "Queries inside box = " << num_inside << "/" << num_queries << " = " 
+            << (double)(num_inside/num_queries) << "%" << std::endl;
+}
+
+    
+  
+  
+  
+

This diff is so big that we needed to truncate the remainder.

https://bitbucket.org/fathomteam/moab/commits/6b770f20a05a/
Changeset:   6b770f20a05a
Branch:      None
User:        tautges
Date:        2013-03-13 22:19:38
Summary:     Commit from MOABtree repo, to 622f81cef.

Affected #:  9 files

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3181e16
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,176 @@
+MOABConfig.cmake
+aclocal.m4
+autom4te.cache/
+config.h
+config.h.in
+config.log
+config.lt
+config.status
+config/config.guess
+config/config.sub
+config/depcomp
+config/install-sh
+config/libtool.m4
+config/ltmain.sh
+config/ltoptions.m4
+config/ltsugar.m4
+config/ltversion.m4
+config/lt~obsolete.m4
+config/missing
+configure
+doc/config.tex
+doc/dev.dox
+doc/user.dox
+examples/examples.make
+itaps/iBase_f.h
+itaps/igeom/FBiGeom-Defs.inc
+itaps/imesh/iMesh-Defs.inc
+itaps/imesh/iMeshP_extensions_protos.h
+itaps/imesh/iMeshP_protos.h
+itaps/imesh/iMesh_extensions_protos.h
+itaps/imesh/iMesh_protos.h
+libtool
+moab.make
+src/FCDefs.h
+src/MBCN_protos.h
+src/MOAB_FCDefs.h
+src/moab/EntityHandle.hpp
+src/moab/Version.h
+src/moab/stamp-h2
+src/moab/stamp-h3
+src/parallel/moab_mpi_config.h
+src/parallel/stamp-h4
+src/stamp-h5
+stamp-h1
+tools/mbcoupler/tests/
+tools/mbzoltan/Config.moab
+tools/vtkMOABReader/CMakeLists.txt
+tools/vtkMOABReaderNew/CMakeLists.txt
+.deps
+Makefile.in
+Makefile
+*/Makefile.in
+*/Makefile
+*/**/Makefile.in
+*/**/Makefile
+makefile
+include
+lib
+bin
+*.o
+*.a
+*.la
+*.lai
+*.lo
+*.log
+*~
+*.rej
+.libs
+diffs
+src/io/mhdf/h5minfo
+src/io/mhdf/h5mvalidate
+examples/FileRead
+examples/GeomSetHierarchy
+examples/KDTree
+examples/GetEntities
+examples/ObbTree
+examples/SetsNTags
+examples/SkinMesh
+examples/SurfArea
+examples/itaps/FindConnectF
+examples/itaps/ListSetsNTagsCXX
+examples/itaps/ListSetsNTagsF90
+examples/itaps/TagIterateC
+examples/itaps/TagIterateF
+itaps/imesh/FindAdjacencyF90
+itaps/imesh/MOAB_iMesh_extensions_tests
+itaps/imesh/MOAB_iMesh_unit_tests
+itaps/imesh/ScdMeshF77
+itaps/imesh/ScdMeshF90
+itaps/imesh/testc_cbind
+moab.config
+share/doc/moab
+share/man/man1
+test/mbfacet_test
+test/CMakeLists.txt
+test/elem_eval_test
+test/scdseq_test
+test/file_options_test
+test/kd_tree_test
+test/h5file/h5regression
+test/h5file/h5legacy
+test/h5file/dump_sets
+test/h5file/h5portable
+test/h5file/h5partial
+test/h5file/h5sets_test
+test/h5file/h5varlen
+test/h5file/h5test
+test/mesh_set_test
+test/kd_tree_time
+test/var_len_test_no_template
+test/moab_test
+test/kd_tree_tool
+test/oldinc/test_oldinc
+test/mbground_test
+test/test_prog_opt
+test/seq_man_test
+test/obb/obb_tree_tool
+test/obb/obb_test
+test/obb/obb_time
+test/reorder_test
+test/homxform_test
+test/bsp_tree_test
+test/tag_test
+test/obb_test
+test/cropvol_test
+test/range_test
+test/gttool_test
+test/test_adj
+test/bsp_tree_poly_test
+test/TestRunner.hpp
+test/xform_test
+test/mbcn_test
+test/adaptive_kd_tree_tests
+test/perf/perftool
+test/perf/tstt_perf_binding
+test/perf/runtest
+test/perf/seqperf
+test/perf/adj_time
+test/perf/perf
+test/perf/point_in_elem
+test/io/ideas_test
+test/io/read_ucd_nc
+test/io/exodus_test
+test/io/read_nc
+test/io/smf_test
+test/io/tqdcfr
+test/io/cub_file_test
+test/io/nastran_test
+test/io/stl_test
+test/io/gmsh_test
+test/io/readutil_test
+test/io/ccmio_test
+test/io/vtk_test
+test/dual/dual_test
+test/coords_connect_iterate
+test/var_len_test
+test/geom_util_test
+tools/mbdepth
+tools/mbgsets
+tools/mbmem
+tools/mbsurfplot
+tools/mbsize
+tools/mbconvert
+tools/dagmc/dagmc_preproc
+tools/dagmc/pt_vol_test
+tools/dagmc/ray_fire_test
+tools/dagmc/test_geom
+tools/dagmc/quads_to_tris
+tools/spheredecomp
+tools/mbskin
+tools/mbtagprop
+tools/hexmodops
+test/*.g
+test/*.gen
+test/io/*.g
+test/io/*.ccmg

diff --git a/src/AdaptiveKDTree.cpp b/src/AdaptiveKDTree.cpp
index d4d27b3..0c2f67e 100644
--- a/src/AdaptiveKDTree.cpp
+++ b/src/AdaptiveKDTree.cpp
@@ -179,6 +179,9 @@ namespace moab {
       }
   
       delete_tree( *tree_root_set );
+
+      treeStats.reset();
+      
       return rval;
     }
 
@@ -568,11 +571,14 @@ namespace moab {
   
       for (;;) {
         childVect.clear();
+        treeTool->treeStats.nodes_visited()++; // not sure whether this is the visit or the push_back below
         rval = treeTool->moab()->get_child_meshsets( mStack.back().entity, childVect );
         if (MB_SUCCESS != rval)
           return rval;
-        if (childVect.empty()) // leaf
+        if (childVect.empty()) { // leaf
+          treeTool->treeStats.leaves_visited()++;
           break;
+        }
   
         rval = treeTool->get_split_plane( mStack.back().entity, plane );
         if (MB_SUCCESS != rval)
@@ -602,7 +608,9 @@ namespace moab {
         // If the stack is empty after this pop, then we've reached the end.
       node = mStack.back();
       mStack.pop_back();
-  
+      treeTool->treeStats.nodes_visited()++;
+      if (mStack.empty()) treeTool->treeStats.leaves_visited()++;
+
       while(!mStack.empty()) {
           // Get data for parent entity
         parent = mStack.back();
@@ -620,6 +628,7 @@ namespace moab {
           mBox[direction][plane.norm] = node.coord;
             // push right child on stack
           node.entity = childVect[direction];
+          treeTool->treeStats.nodes_visited()++; // changed node
           node.coord = mBox[opposite][plane.norm];
           mStack.push_back( node );
             // change from box of parent to box of right child
@@ -633,6 +642,7 @@ namespace moab {
         assert( childVect[direction] == node.entity );
         mBox[opposite][plane.norm] = node.coord;
         node = parent;
+        treeTool->treeStats.nodes_visited()++;
         mStack.pop_back();
       }
   
@@ -835,6 +845,7 @@ namespace moab {
                                             double& t_enter, 
                                             double& t_exit ) const
     {
+      treeTool->treeStats.leaf_object_tests()++;
       return GeomUtil::ray_box_intersect( CartVect(box_min()),
                                           CartVect(box_max()),
                                           CartVect(ray_point),
@@ -886,6 +897,7 @@ namespace moab {
   
         // vertices
       for (i = elems.begin(); i != elem_begin; ++i) {
+        tool->tree_stats().leaf_object_tests()++;
         rval = moab->get_coords( &*i, 1, coords[0].array() );
         if (MB_SUCCESS != rval)
           return rval;
@@ -906,6 +918,7 @@ namespace moab {
   
         // non-polyhedron elements
       for (i = elem_begin; i != poly_begin; ++i) {
+        tool->tree_stats().leaf_object_tests()++;
         rval = moab->get_connectivity( *i, conn, count, true );
         if (MB_SUCCESS != rval) 
           return rval;
@@ -945,6 +958,7 @@ namespace moab {
   
         // polyhedra
       for (i = poly_begin; i != set_begin; ++i) {
+        tool->tree_stats().leaf_object_tests()++;
         rval = moab->get_connectivity( *i, conn, count, true );
         if (MB_SUCCESS != rval) 
           return rval;
@@ -978,6 +992,7 @@ namespace moab {
         // sets
       CartVect tmin, tmax;
       for (i = set_begin; i != elems.end(); ++i) {
+        tool->tree_stats().leaf_object_tests()++;
         rval = tool->compute_bounding_box( *i, tmin, tmax);
         if (MB_SUCCESS != rval)
           return rval;
@@ -2030,10 +2045,6 @@ namespace moab {
           min_depth = iter.depth();
         ++k;
       }
-      std::cout << std::endl << "# of leafs: " << k+1 << std::endl;
-      std::cout << std::endl << "max depth: " << max << std::endl;
-      std::cout << std::endl << "min depth: " << min << std::endl;
-      std::cout << std::endl << "# of elements " << num_of_elements << std::endl;
       return MB_SUCCESS;
     }
           
@@ -2041,8 +2052,6 @@ namespace moab {
                                        double min[3], double max[3], 
                                        unsigned int &dep) 
     {
-      if (root != myRoot) return MB_FAILURE;
-      
       ErrorCode result = get_bounding_box(min, max, &root);
       if (MB_SUCCESS != result) return result;
   

diff --git a/src/Makefile.am b/src/Makefile.am
index d27d10c..d7107d6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -200,7 +200,7 @@ nobase_libMOAB_la_include_HEADERS = \
   moab/SpatialLocator.hpp \
   moab/SpectralMeshTool.hpp \
   moab/Tree.hpp \
-  moab/TreeTravStats.hpp \
+  moab/TreeStats.hpp \
   moab/Types.hpp \
   moab/UnknownInterface.hpp \
   moab/Util.hpp \

diff --git a/src/SpatialLocator.cpp b/src/SpatialLocator.cpp
index d5d7b3b..7848b95 100644
--- a/src/SpatialLocator.cpp
+++ b/src/SpatialLocator.cpp
@@ -83,15 +83,15 @@ namespace moab
 
           // loop over the range_leaf
         bool tmp_inside;
-        for(Range::iterator iter = range_leaf.begin(); iter != range_leaf.end(); iter++)
+        for(Range::iterator rit = range_leaf.begin(); rit != range_leaf.end(); rit++)
         {
           bool *is_ptr = (is_inside ? is_inside+i3 : &tmp_inside);      
-          rval = elemEval->set_ent_handle(*iter); 
+          rval = elemEval->set_ent_handle(*rit); 
           if (MB_SUCCESS != rval) return rval;
           rval = elemEval->reverse_eval(pos+i3, 0.0, params+i3, is_ptr);
           if (MB_SUCCESS != rval) return rval;
           if (*is_ptr) {
-            ents[i] = *iter;
+            ents[i] = *rit;
             break;
           }
         }

diff --git a/src/moab/AdaptiveKDTree.hpp b/src/moab/AdaptiveKDTree.hpp
index 1458ce0..9fe87b0 100644
--- a/src/moab/AdaptiveKDTree.hpp
+++ b/src/moab/AdaptiveKDTree.hpp
@@ -236,6 +236,8 @@ namespace moab {
 
   private:
 
+      friend class AdaptiveKDTreeIter;
+
         /** \brief Parse options for tree creation
          * \param options Options passed in by application
          * \return Failure is returned if any options were passed in and not interpreted; could mean

diff --git a/src/moab/SpatialLocator.hpp b/src/moab/SpatialLocator.hpp
index 0955700..bc5be70 100644
--- a/src/moab/SpatialLocator.hpp
+++ b/src/moab/SpatialLocator.hpp
@@ -26,7 +26,7 @@ namespace moab {
       SpatialLocator(Interface *impl, Range &elems, Tree *tree = NULL, ElemEvaluator *eval = NULL);
 
         /* destructor */
-      ~SpatialLocator() {}
+      virtual ~SpatialLocator() {}
 
         /* add elements to be searched */
       ErrorCode add_elems(Range &elems);

diff --git a/src/moab/Tree.hpp b/src/moab/Tree.hpp
index e2b25e6..b30326f 100644
--- a/src/moab/Tree.hpp
+++ b/src/moab/Tree.hpp
@@ -9,6 +9,7 @@
 #include "moab/Interface.hpp"
 #include "moab/CartVect.hpp"
 #include "moab/FileOptions.hpp"
+#include "moab/TreeStats.hpp"
 
 #include <string>
 #include <vector>
@@ -187,8 +188,13 @@ namespace moab {
       
         /** \brief Get max entities per leaf set on tree */
       double get_max_per_leaf() {return maxPerLeaf;}
+
+        /** \brief Get tree traversal stats object */
+      TreeStats &tree_stats() {return treeStats;}
+      
+        /** \brief Get tree traversal stats object */
+      const TreeStats &tree_stats() const {return treeStats;}
       
-            
   protected:
 
         /** \brief Parse options common to all trees
@@ -236,6 +242,9 @@ namespace moab {
 
         // tag name used for boxTag
       std::string boxTagName;
+
+        // tree traversal stats
+      TreeStats treeStats;
       
   private:
 

diff --git a/src/moab/TreeStats.hpp b/src/moab/TreeStats.hpp
new file mode 100644
index 0000000..86dd79f
--- /dev/null
+++ b/src/moab/TreeStats.hpp
@@ -0,0 +1,97 @@
+/**\file TreeStats.hpp
+ * \class moab::TreeStats
+ * \brief Traversal statistics accumulating and reporting
+ *
+ * Class to accumulate statistics on traversal performance. This structure contains the
+ * count of nodes visited at each level in a tree, and the count of traversals that ended
+ * at each level.  One TrvStats structure can be used with multiple trees or multiple
+ * queries, or used on only a single tree or a single query.
+ *
+ * Note that these traversal statistics are not related to the stats() query below,
+ * which calculates static information about a tree.  These statistics relate
+ * to a tree's dynamic behavior on particular operations.
+ */
+
+#ifndef TREESTATS_HPP
+#define TREESTATS_HPP
+
+#include <vector>
+#include <iostream>
+#include <string>
+
+namespace moab 
+{
+    class TreeStats{
+  public:
+        //! constructor
+      TreeStats() 
+              : leafObjectTests(0) 
+          {}      
+      
+        //! return counts of nodes visited, indexed by tree depth.  
+        //! the counts include both leaves and interior nodes
+      const unsigned int &nodes_visited() const
+          {return nodesVisited;}
+
+        //! return counts of tree leaves visited, indexed by tree depth
+      const unsigned int &leaves_visited() const
+          {return leavesVisited;}
+
+        //! return counts of traversals ended, indexed by tree depth
+      const unsigned int &num_traversals() const 
+          {return numTraversals;}
+
+        //! return counts of nodes visited, indexed by tree depth.  
+        //! the counts include both leaves and interior nodes
+      unsigned int &nodes_visited() 
+          {return nodesVisited;}
+
+        //! return counts of tree leaves visited, indexed by tree depth
+      unsigned int &leaves_visited()
+          {return leavesVisited;}
+
+        //! return counts of traversals ended, indexed by tree depth
+      unsigned int &num_traversals()
+          {return numTraversals;}
+
+        //! return total number of leaf-object tests (ray-triangle, point in elem, etc.) performed
+      const unsigned int &leaf_object_tests() const
+          {return leafObjectTests;}
+
+      unsigned int &leaf_object_tests()
+          {return leafObjectTests;}
+
+        //! reset all counters on this structure
+      void reset();
+              
+        //! print the contents of this structure to given stream
+      void print() const ;
+
+  private:
+      unsigned int nodesVisited;
+      unsigned int leavesVisited;
+      unsigned int numTraversals;
+      unsigned int leafObjectTests;
+    };
+
+    inline void TreeStats::reset()
+    {
+      nodesVisited = 0;
+      leavesVisited = 0;
+      numTraversals = 0;
+      leafObjectTests = 0;
+    }
+    
+    inline void TreeStats::print() const {
+      std::cout << "NodesVisited      = " << nodesVisited << std::endl;
+      std::cout << "LeavesVisited     = " << leavesVisited << std::endl;
+      std::cout << "Num Traversals    = " << numTraversals << std::endl;
+      std::cout << "Leaf Object Tests = " << leafObjectTests << std::endl;
+    }
+}
+
+    
+      
+
+
+#endif

diff --git a/test/elem_eval_test.cpp b/test/elem_eval_test.cpp
new file mode 100644
index 0000000..75ed95e
--- /dev/null
+++ b/test/elem_eval_test.cpp
@@ -0,0 +1,143 @@
+/**
+ * \file elem_eval_test.cpp
+ *
+ * \brief test ElemEvaluator and the various element types in MOAB
+ *
+ */
+#include "moab/Core.hpp"
+#include "moab/ElemEvaluator.hpp"
+#include "moab/LinearHex.hpp"
+#include "moab/LinearTet.hpp"
+#include "moab/QuadraticHex.hpp"
+#include "moab/CartVect.hpp"
+#include "TestUtil.hpp"
+
+#ifdef MESHDIR
+std::string TestDir( STRINGIFY(MESHDIR) );
+#else
+std::string TestDir(".");
+#endif
+
+using namespace moab;
+
+void test_linear_hex();
+void test_linear_tet();
+void test_quadratic_hex();
+
+CartVect hex_verts[] = { 
+      // corners
+    CartVect( -1, -1, -1 ), CartVect( 1, -1, -1 ), CartVect( 1, 1, -1 ), CartVect( -1, 1, -1 ),
+    CartVect( -1, -1, 1 ), CartVect( 1, -1, 1 ), CartVect( 1, 1, 1 ), CartVect( -1, 1, 1 ),
+      // mid-edge (bottom, middle, top)
+    CartVect( 0, -1, -1 ), CartVect( 1, 0, -1 ), CartVect( 0, 1, -1 ), CartVect( -1, 0, -1 ),
+    CartVect( -1, -1, 0 ), CartVect( 1, -1, 0 ), CartVect( 1, 1, 0 ), CartVect( -1, 1, 0 ),
+    CartVect( 0, -1, 1 ), CartVect( 1, 0, 1 ), CartVect( 0, 1, 1 ), CartVect( -1, 0, 1 ),
+      // mid-face (middle, bottom, top)
+    CartVect( 0, -1, 0 ), CartVect( 1, 0, 0 ), CartVect( 0, 1, 0 ), CartVect( -1, 0, 0 ),
+    CartVect( 0, 0, -1 ), CartVect( 0, 0, 1 ), 
+      // mid-element
+    CartVect( 0, 0, 0 )
+};
+
+void test_eval(ElemEvaluator &ee, bool test_integrate) 
+{
+  
+  CartVect params, posn, params2;
+  bool is_inside;
+  const double EPS1 = 1e-6;
+  Matrix3 jacob;
+  ErrorCode rval;
+  
+  for (params[0] = -1; params[0] <= 1; params[0] += 0.2) {
+    for (params[1] = -1; params[1] <= 1; params[1] += 0.2) {
+      for (params[2] = -1; params[2] <= 1; params[2] += 0.2) {
+
+          // forward/reverse evaluation should get back to the same point, within tol
+        rval = ee.eval(params, posn.array()); CHECK_ERR(rval);
+        rval = ee.reverse_eval(posn, EPS1, params2, &is_inside); CHECK_ERR(rval);
+        CHECK_REAL_EQUAL(0.0, (params - params2).length(), EPS1);
+
+          // jacobian should be >= 0
+        rval = ee.jacobian(params, jacob); CHECK_ERR(rval);
+        CHECK(jacob.determinant() >= 0.0);
+        
+      }
+    }
+  }
+
+    // tag equal to coordinates should integrate to avg position, since volume is 1
+  Tag tag;
+  rval = ee.get_moab()->tag_get_handle(NULL, 3, MB_TYPE_DOUBLE, tag, MB_TAG_DENSE | MB_TAG_CREAT); CHECK_ERR(rval);
+  rval = ee.get_moab()->tag_set_data(tag, ee.get_vert_handles(), ee.get_num_verts(), hex_verts[0].array()); CHECK_ERR(rval);
+  
+  rval = ee.set_tag_handle(tag, 0); CHECK_ERR(rval);
+
+  if (test_integrate) {
+    CartVect integral, avg(0.0);
+    rval = ee.integrate(integral.array()); CHECK_ERR(rval);
+    CHECK_REAL_EQUAL(0.0, (avg - integral).length(), EPS1);
+  }
+  
+}
+
+int main()
+{
+  int failures = 0;
+  
+  failures += RUN_TEST(test_linear_hex);
+  failures += RUN_TEST(test_quadratic_hex);
+  failures += RUN_TEST(test_linear_tet);
+
+  return failures;
+}
+
+void test_linear_hex() 
+{
+  Core mb;
+  Range verts;
+  ErrorCode rval = mb.create_vertices((double*)hex_verts, 8, verts); CHECK_ERR(rval);
+  EntityHandle hex;
+  std::vector<EntityHandle> connect;
+  std::copy(verts.begin(), verts.end(), std::back_inserter(connect));
+  rval = mb.create_element(MBHEX, connect.data(), 8, hex); CHECK_ERR(rval);
+  
+  ElemEvaluator ee(&mb, hex, 0);
+  ee.set_tag_handle(0, 0);
+  ee.set_eval_set(MBHEX, LinearHex::eval_set());
+
+  test_eval(ee, true);
+}
+
+void test_quadratic_hex() 
+{
+  Core mb;
+  Range verts;
+  ErrorCode rval = mb.create_vertices((double*)hex_verts, 27, verts); CHECK_ERR(rval);
+  EntityHandle hex;
+  std::vector<EntityHandle> connect;
+  std::copy(verts.begin(), verts.end(), std::back_inserter(connect));
+  rval = mb.create_element(MBHEX, connect.data(), 27, hex); CHECK_ERR(rval);
+  
+  ElemEvaluator ee(&mb, hex, 0);
+  ee.set_tag_handle(0, 0);
+  ee.set_eval_set(MBHEX, QuadraticHex::eval_set());
+
+  test_eval(ee, false);
+}
+
+void test_linear_tet() 
+{
+  Core mb;
+  Range verts;
+  ErrorCode rval = mb.create_vertices((double*)hex_verts[1].array(), 4, verts); CHECK_ERR(rval);
+  EntityHandle tet;
+  std::vector<EntityHandle> connect;
+  std::copy(verts.begin(), verts.end(), std::back_inserter(connect));
+  rval = mb.create_element(MBTET, connect.data(), 4, tet); CHECK_ERR(rval);
+  
+  ElemEvaluator ee(&mb, tet, 0);
+  ee.set_tag_handle(0, 0);
+  ee.set_eval_set(MBTET, LinearTet::eval_set());
+
+  test_eval(ee, false);
+}


https://bitbucket.org/fathomteam/moab/commits/4e5918b9cd98/
Changeset:   4e5918b9cd98
Branch:      None
User:        tautges
Date:        2013-03-16 19:17:27
Summary:     Many bug fixes, deleting src/ElemUtil.cpp and src/moab/ElemUtil.hpp (keeping
the ones in tools/mbcoupler), and adding a performance test of element functions.

Affected #:  7 files

diff --git a/src/ElemUtil.cpp b/src/ElemUtil.cpp
deleted file mode 100644
index cc00d00..0000000
--- a/src/ElemUtil.cpp
+++ /dev/null
@@ -1,695 +0,0 @@
-#include <iostream>
-#include <limits>
-#include <assert.h>
-
-#include "ElemUtil.hpp"
-#include "types.h"
-
-namespace moab { 
-namespace Element {
-
-    bool Map::evaluate_reverse(const CartVect& x, CartVect &params, double tol, const CartVect& x0) const {
-        // TODO: should differentiate between epsilons used for
-        // Newton Raphson iteration, and epsilons used for curved boundary geometry errors
-        // right now, fix the tolerance used for NR
-      const double error_tol_sqr = tol*tol;
-      double det;
-      params = x0;
-      CartVect delta = evaluate(params) - x;
-      Matrix3 J;
-
-      int iters=0;
-      while (delta % delta > error_tol_sqr) {
-        if(++iters>10)
-          return false;
-
-        J = jacobian(params);
-        det = J.determinant();
-        if (det < std::numeric_limits<double>::epsilon())
-          return false;
-        params -= J.inverse(1.0/det) * delta;
-        delta = evaluate( params ) - x;
-      }
-      return true;
-    }// Map::evaluate_reverse()
-
-    const double LinearHex::corner[8][3] = { { -1, -1, -1 },
-                                             {  1, -1, -1 },
-                                             {  1,  1, -1 },
-                                             { -1,  1, -1 },
-                                             { -1, -1,  1 },
-                                             {  1, -1,  1 },
-                                             {  1,  1,  1 },
-                                             { -1,  1,  1 } };
-
-      /* For each point, its weight and location are stored as an array.
-         Hence, the inner dimension is 2, the outer dimension is gauss_count.
-         We use a one-point Gaussian quadrature, since it integrates linear functions exactly.
-      */
-    const double LinearHex::gauss[1][2] = { {  2.0,           0.0          } };
-
-    CartVect LinearHex::evaluate( const CartVect& params ) const {
-      CartVect x(0.0);
-      for (unsigned i = 0; i < 8; ++i) {
-        const double N_i = 
-            (1 + params[0]*corner[i][0])
-            * (1 + params[1]*corner[i][1])
-            * (1 + params[2]*corner[i][2]);
-        x += N_i * this->vertex[i];
-      }
-      x *= 0.125;
-      return x;
-    }// LinearHex::evaluate
-
-    Matrix3 LinearHex::jacobian( const CartVect& params ) const {
-      Matrix3 J(0.0);
-      for (unsigned i = 0; i < 8; ++i) {
-        const double   params_p = 1 + params[0]*corner[i][0];
-        const double  eta_p = 1 + params[1]*corner[i][1];
-        const double zeta_p = 1 + params[2]*corner[i][2];
-        const double dNi_dparams   = corner[i][0] * eta_p * zeta_p;
-        const double dNi_deta  = corner[i][1] *  params_p * zeta_p;
-        const double dNi_dzeta = corner[i][2] *  params_p *  eta_p;
-        J(0,0) += dNi_dparams   * vertex[i][0];
-        J(1,0) += dNi_dparams   * vertex[i][1];
-        J(2,0) += dNi_dparams   * vertex[i][2];
-        J(0,1) += dNi_deta  * vertex[i][0];
-        J(1,1) += dNi_deta  * vertex[i][1];
-        J(2,1) += dNi_deta  * vertex[i][2];
-        J(0,2) += dNi_dzeta * vertex[i][0];
-        J(1,2) += dNi_dzeta * vertex[i][1];
-        J(2,2) += dNi_dzeta * vertex[i][2];
-      }
-      return J *= 0.125;
-    }// LinearHex::jacobian()
-
-    void LinearHex::evaluate_vector(const CartVect& params, const double *field_values, int num_tuples, double *eval) const {
-      for (int i = 0; i < num_tuples; i++) eval[i] = 0.0;
-      for (unsigned i = 0; i < 8; ++i) {
-        const double N_i = (1 + params[0]*corner[i][0])
-            * (1 + params[1]*corner[i][1])
-            * (1 + params[2]*corner[i][2]);
-        for (int j = 0; j < num_tuples; j++) eval[j] += N_i * field_values[i*num_tuples+j];
-      }
-      for (int i = 0; i < num_tuples; i++) eval[i] *= 0.125;
-    }// LinearHex::evaluate_vector()
-
-    void LinearHex::integrate_vector(const double *field_values, int num_tuples, double *integral) const {
-      double tmp_integral[8];
-      for (int i = 0; i < num_tuples; i++) integral[i] = 0.0;
-      CartVect x;
-      for(unsigned int j1 = 0; j1 < this->gauss_count; ++j1) {
-        x[0] = this->gauss[j1][1];
-        double w1 = this->gauss[j1][0];
-        for(unsigned int j2 = 0; j2 < this->gauss_count; ++j2) {
-          x[1] = this->gauss[j2][1];
-          double w2 = this->gauss[j2][0];
-          for(unsigned int j3 = 0; j3 < this->gauss_count; ++j3) {
-            x[2] = this->gauss[j3][1];
-            double w3 = this->gauss[j3][0];
-            this->evaluate_vector(x,field_values, num_tuples, tmp_integral);
-            double tmp_det =  w1*w2*w3*this->det_jacobian(x);
-            for (int i = 0; i < num_tuples; i++) integral[i] += tmp_integral[i]*tmp_det;
-          }
-        }
-      }
-    }// LinearHex::integrate_vector()
-
-    bool LinearHex::is_inside(const CartVect & params, double tol) const
-    {
-        // just look at the box+tol here
-      return ( params[0]>=-1.-tol) && (params[0]<=1.+tol) &&
-          ( params[1]>=-1.-tol) && (params[1]<=1.+tol) &&
-          ( params[2]>=-1.-tol) && (params[2]<=1.+tol);
-    }
-
-      // those are not just the corners, but for simplicity, keep this name
-      //
-    const int QuadraticHex::corner[27][3] = {
-        { -1, -1, -1 },
-        {  1, -1, -1 },
-        {  1,  1, -1 },  // corner nodes: 0-7
-        { -1,  1, -1 },  // mid-edge nodes: 8-19
-        { -1, -1,  1 },  // center-face nodes 20-25  center node  26
-        {  1, -1,  1 },  //
-        {  1,  1,  1 },
-        { -1,  1,  1 }, //                    4   ----- 19   -----  7
-        {  0, -1, -1 }, //                .   |                 .   |
-        {  1,  0, -1 }, //            16         25         18      |
-        {  0,  1, -1 }, //         .          |          .          |
-        { -1,  0, -1 }, //      5   ----- 17   -----  6             |
-        { -1, -1,  0 }, //      |            12       | 23         15
-        {  1, -1,  0 }, //      |                     |             |
-        {  1,  1,  0 }, //      |     20      |  26   |     22      |
-        { -1,  1,  0 }, //      |                     |             |
-        {  0, -1,  1 }, //     13         21  |      14             |
-        {  1,  0,  1 }, //      |             0   ----- 11   -----  3
-        {  0,  1,  1 }, //      |         .           |         .
-        { -1,  0,  1 }, //      |      8         24   |     10
-        {  0, -1,  0 }, //      |  .                  |  .
-        {  1,  0,  0 }, //      1   -----  9   -----  2
-        {  0,  1,  0 }, //
-        { -1,  0,  0 },
-        {  0,  0, -1 },
-        {  0,  0,  1 },
-        {  0,  0,  0 }
-    };
-      //QuadraticHex::QuadraticHex(const std::vector<CartVect>& vertices) : Map(vertices){};
-    QuadraticHex::QuadraticHex():Map(0) {
-    }
-
-    double SH(const int i, const double params)
-    {
-      switch (i)
-      {
-        case -1: return (params*params-params)/2;
-        case 0: return 1-params*params;
-        case 1: return (params*params+params)/2;
-        default: return 0.;
-      }
-    }
-    double DSH(const int i, const double params)
-    {
-      switch (i)
-      {
-        case -1: return params-0.5;
-        case 0: return -2*params;
-        case 1: return params+0.5;
-        default: return 0.;
-      }
-    }
-
-    CartVect QuadraticHex::evaluate( const CartVect& params ) const
-    {
-
-      CartVect x(0.0);
-      for (int i=0; i<27; i++)
-      {
-        const double sh= SH(corner[i][0], params[0])
-            *SH(corner[i][1], params[1])
-            *SH(corner[i][2], params[2]);
-        x+=sh* vertex[i];
-      }
-
-      return x;
-    }
-
-    bool QuadraticHex::is_inside(const CartVect & params, double tol) const
-    {// just look at the box+tol here
-      return ( params[0]>=-1.-tol) && (params[0]<=1.+tol) &&
-          ( params[1]>=-1.-tol) && (params[1]<=1.+tol) &&
-          ( params[2]>=-1.-tol) && (params[2]<=1.+tol);
-    }
-
-    Matrix3  QuadraticHex::jacobian(const CartVect& params) const
-    {
-      Matrix3 J(0.0);
-      for (int i=0; i<27; i++)
-      {
-        const double sh[3]={ SH(corner[i][0], params[0]),
-                             SH(corner[i][1], params[1]),
-                             SH(corner[i][2], params[2]) };
-        const double dsh[3]={ DSH(corner[i][0], params[0]),
-                              DSH(corner[i][1], params[1]),
-                              DSH(corner[i][2], params[2]) };
-
-
-        for (int j=0; j<3; j++)
-        {
-          J(j,0)+=dsh[0]*sh[1]*sh[2]*vertex[i][j]; // dxj/dr first column
-          J(j,1)+=sh[0]*dsh[1]*sh[2]*vertex[i][j]; // dxj/ds
-          J(j,2)+=sh[0]*sh[1]*dsh[2]*vertex[i][j]; // dxj/dt
-        }
-      }
-
-
-      return J;
-    }
-    void QuadraticHex::evaluate_vector(const CartVect& params, const double *field_values, int num_tuples, double *eval) const
-    {
-      for (int i = 0; i < num_tuples; i++) eval[i] = 0.0;
-      for (int i=0; i<27; i++)
-      {
-        const double sh= SH(corner[i][0], params[0])
-            *SH(corner[i][1], params[1])
-            *SH(corner[i][2], params[2]);
-        for (int j = 0; j < num_tuples; j++) 
-          eval[j] += sh* field_values[i*num_tuples+j];
-      }
-    }
-
-    void QuadraticHex::integrate_vector(const double *field_vertex_values, int num_tuples, double *integral) const
-  {
-  }
-
-    const double LinearTet::corner[4][3] = { {0,0,0},
-                                             {1,0,0},
-                                             {0,1,0},
-                                             {0,0,1}};
-
-    LinearTet::LinearTet() : Map(0) {
-
-    }// LinearTet::LinearTet()
-
-
-    void LinearTet::set_vertices(const CartVect *v, int num_vs) {
-      this->Map::set_vertices(v, num_vs);
-      this->T = Matrix3(v[1][0]-v[0][0],v[2][0]-v[0][0],v[3][0]-v[0][0],
-                        v[1][1]-v[0][1],v[2][1]-v[0][1],v[3][1]-v[0][1],
-                        v[1][2]-v[0][2],v[2][2]-v[0][2],v[3][2]-v[0][2]);
-      this->T_inverse = this->T.inverse();
-      this->det_T = this->T.determinant();
-      this->det_T_inverse = (0.0 == this->det_T ? HUGE : 1.0/this->det_T);
-    }
-
-
-    void LinearTet::evaluate_vector(const CartVect& params, const double *field_values, int num_tuples, double *eval) const {
-      std::vector<double> f0(num_tuples);
-      for (int j = 0; j < num_tuples; j++) {
-        f0[j] = field_values[j];
-        eval[j] = f0[j];
-      }
-      for (unsigned i = 1; i < 4; ++i) {
-        for (int j = 0; j < num_tuples; j++)
-          eval[j] += (field_values[i*num_tuples+j]-f0[j])*params[i-1];
-      }
-    }
-
-    void LinearTet::integrate_vector(const double *field_values, int num_tuples, double *integral) const {
-      for (int i = 0; i < num_tuples; i++) integral[i] = 0.0;
-      for(unsigned int i = 0; i < 4; ++i) {
-        for (int j = 0; j < num_tuples; j++)
-          integral[j] += field_values[i*num_tuples+j];
-      }
-      double tmp = this->det_T/24.0;
-      for (int i = 0; i < num_tuples; i++) integral[i] *= tmp;
-    }
-
-    bool LinearTet::is_inside(const CartVect & params, double tol) const
-    {
-        // linear tet space is a tetra with vertices (0,0,0), (1,0,0), (0,1,0), (0, 0, 1)
-        // first check if outside bigger box, then below the plane x+y+z=1
-      return ( params[0]>=-tol)  &&
-          ( params[1]>=-tol)  &&
-          ( params[2]>=-tol)  &&
-          ( params[0]+params[1]+params[2] < 1.0+tol);
-    }
-      // SpectralHex
-
-      // filescope for static member data that is cached
-    int SpectralHex::_n;
-    double *SpectralHex::_z[3];
-    lagrange_data SpectralHex::_ld[3];
-    opt_data_3 SpectralHex::_data;
-    double * SpectralHex::_odwork;
-
-    bool SpectralHex::_init = false;
-
-    SpectralHex::SpectralHex() : Map(0)
-    {
-    }
-      // the preferred constructor takes pointers to GL blocked positions
-    SpectralHex::SpectralHex(int order, double * x, double *y, double *z) : Map(0)
-    {
-      Init(order);
-      _xyz[0]=x; _xyz[1]=y; _xyz[2]=z;
-    }
-    SpectralHex::SpectralHex(int order) : Map(0)
-    {
-      Init(order);
-      _xyz[0]=_xyz[1]=_xyz[2]=NULL;
-    }
-    SpectralHex::~SpectralHex()
-    {
-      if (_init)
-        freedata();
-      _init=false;
-    }
-    void SpectralHex::Init(int order)
-    {
-      if (_init && _n==order)
-        return;
-      if (_init && _n!=order)
-      {
-          // TODO: free data cached
-        freedata();
-      }
-        // compute stuff that depends only on order
-      _init = true;
-      _n = order;
-        //triplicates! n is the same in all directions !!!
-      for(int d=0; d<3; d++){
-        _z[d] = tmalloc(double, _n);
-        lobatto_nodes(_z[d], _n);
-        lagrange_setup(&_ld[d], _z[d], _n);
-      }
-      opt_alloc_3(&_data, _ld);
-
-      unsigned int nf = _n*_n, ne = _n, nw = 2*_n*_n + 3*_n;
-      _odwork = tmalloc(double, 6*nf + 9*ne + nw);
-    }
-    void SpectralHex::freedata()
-    {
-      for(int d=0; d<3; d++){
-        free(_z[d]);
-        lagrange_free(&_ld[d]);
-      }
-      opt_free_3(&_data);
-      free(_odwork);
-    }
-
-    void SpectralHex::set_gl_points( double * x, double * y, double *z)
-    {
-      _xyz[0] = x;
-      _xyz[1] = y;
-      _xyz[2] = z;
-    }
-    CartVect SpectralHex::evaluate( const CartVect& params ) const
-    {
-        //piece that we shouldn't want to cache
-      int d=0;
-      for(d=0; d<3; d++){
-        lagrange_0(&_ld[d], params[d]);
-      }
-      CartVect result;
-      for (d=0; d<3; d++)
-      {
-        result[d] = tensor_i3(_ld[0].J,_ld[0].n,
-                              _ld[1].J,_ld[1].n,
-                              _ld[2].J,_ld[2].n,
-                              _xyz[d],   // this is the "field"
-                              _odwork);
-      }
-      return result;
-    }
-      // replicate the functionality of hex_findpt
-    bool SpectralHex::evaluate_reverse(CartVect const & xyz, CartVect &params, double tol, const CartVect &init) const
-    {
-      params = init;
-      
-        //find nearest point
-      double x_star[3];
-      xyz.get(x_star);
-
-      double r[3] = {0, 0, 0 }; // initial guess for parametric coords
-      unsigned c = opt_no_constraints_3;
-      double dist = opt_findpt_3(&_data, (const double **)_xyz, x_star, r, &c);
-        // if it did not converge, get out with throw...
-      if (dist > 0.9e+30)
-        return false;
-        //c tells us if we landed inside the element or exactly on a face, edge, or node
-        // also, dist shows the distance to the computed point.
-        //copy parametric coords back
-      params = r;
-
-      return is_inside(params, tol);
-    }
-    Matrix3  SpectralHex::jacobian(const CartVect& params) const
-    {
-      double x_i[3];
-      params.get(x_i);
-        // set the positions of GL nodes, before evaluations
-      _data.elx[0]=_xyz[0];
-      _data.elx[1]=_xyz[1];
-      _data.elx[2]=_xyz[2];
-      opt_vol_set_intp_3(&_data,x_i);
-      Matrix3 J(0.);
-        // it is organized differently
-      J(0,0) = _data.jac[0]; // dx/dr
-      J(0,1) = _data.jac[1]; // dx/ds
-      J(0,2) = _data.jac[2]; // dx/dt
-      J(1,0) = _data.jac[3]; // dy/dr
-      J(1,1) = _data.jac[4]; // dy/ds
-      J(1,2) = _data.jac[5]; // dy/dt
-      J(2,0) = _data.jac[6]; // dz/dr
-      J(2,1) = _data.jac[7]; // dz/ds
-      J(2,2) = _data.jac[8]; // dz/dt
-      return J;
-    }
-    void SpectralHex::evaluate_vector(const CartVect& params, const double *field, int num_tuples, double *eval) const
-    {
-        //piece that we shouldn't want to cache
-      int d;
-      for(d=0; d<3; d++){
-        lagrange_0(&_ld[d], params[d]);
-      }
-
-      *eval = tensor_i3(_ld[0].J,_ld[0].n,
-                        _ld[1].J,_ld[1].n,
-                        _ld[2].J,_ld[2].n,
-                        field,
-                        _odwork);
-    }
-    void SpectralHex::integrate_vector(const double *field_values, int num_tuples, double *integral) const
-    {
-        // set the position of GL points
-        // set the positions of GL nodes, before evaluations
-      _data.elx[0]=_xyz[0];
-      _data.elx[1]=_xyz[1];
-      _data.elx[2]=_xyz[2];
-      double params[3];
-        //triple loop; the most inner loop is in r direction, then s, then t
-      for (int l = 0; l < num_tuples; l++) integral[l] = 0.0;
-        //double volume = 0;
-      int index=0; // used fr the inner loop
-      for (int k=0; k<_n; k++ )
-      {
-        params[2]=_ld[2].z[k];
-          //double wk= _ld[2].w[k];
-        for (int j=0; j<_n; j++)
-        {
-          params[1]=_ld[1].z[j];
-            //double wj= _ld[1].w[j];
-          for (int i=0; i<_n; i++)
-          {
-            params[0]=_ld[0].z[i];
-              //double wi= _ld[0].w[i];
-            opt_vol_set_intp_3(&_data,params);
-            double wk= _ld[2].J[k];
-            double wj= _ld[1].J[j];
-            double wi= _ld[0].J[i];
-            Matrix3 J(0.);
-              // it is organized differently
-            J(0,0) = _data.jac[0]; // dx/dr
-            J(0,1) = _data.jac[1]; // dx/ds
-            J(0,2) = _data.jac[2]; // dx/dt
-            J(1,0) = _data.jac[3]; // dy/dr
-            J(1,1) = _data.jac[4]; // dy/ds
-            J(1,2) = _data.jac[5]; // dy/dt
-            J(2,0) = _data.jac[6]; // dz/dr
-            J(2,1) = _data.jac[7]; // dz/ds
-            J(2,2) = _data.jac[8]; // dz/dt
-            double bm = wk*wj*wi* J.determinant();
-            for (int l = 0; l < num_tuples; l++)
-              integral[l]+= bm*field_values[num_tuples*index+l];
-              //volume +=bm;
-          }
-        }
-      }
-        //std::cout << "volume: " << volume << "\n";
-    }
-      // this is the same as a linear hex, although we should not need it
-    bool SpectralHex::is_inside(const CartVect & params, double tol) const
-    {
-        // just look at the box+tol here
-      return ( params[0]>=-1.-tol) && (params[0]<=1.+tol) &&
-          ( params[1]>=-1.-tol) && (params[1]<=1.+tol) &&
-          ( params[2]>=-1.-tol) && (params[2]<=1.+tol);
-    }
-
-      // SpectralHex
-
-      // filescope for static member data that is cached
-    int SpectralQuad::_n;
-    double *SpectralQuad::_z[2];
-    lagrange_data SpectralQuad::_ld[2];
-    opt_data_2 SpectralQuad::_data;
-    double * SpectralQuad::_odwork;
-    double * SpectralQuad::_glpoints;
-    bool SpectralQuad::_init = false;
-
-    SpectralQuad::SpectralQuad() : Map(0)
-    {
-    }
-      // the preferred constructor takes pointers to GL blocked positions
-    SpectralQuad::SpectralQuad(int order, double * x, double *y, double *z) : Map(0)
-    {
-      Init(order);
-      _xyz[0]=x; _xyz[1]=y; _xyz[2]=z;
-    }
-    SpectralQuad::SpectralQuad(int order) : Map(4)
-    {
-      Init(order);
-      _xyz[0]=_xyz[1]=_xyz[2]=NULL;
-    }
-    SpectralQuad::~SpectralQuad()
-    {
-      if (_init)
-        freedata();
-      _init=false;
-    }
-    void SpectralQuad::Init(int order)
-    {
-      if (_init && _n==order)
-        return;
-      if (_init && _n!=order)
-      {
-          // TODO: free data cached
-        freedata();
-      }
-        // compute stuff that depends only on order
-      _init = true;
-      _n = order;
-        //duplicates! n is the same in all directions !!!
-      for(int d=0; d<2; d++){
-        _z[d] = tmalloc(double, _n);
-        lobatto_nodes(_z[d], _n);
-        lagrange_setup(&_ld[d], _z[d], _n);
-      }
-      opt_alloc_2(&_data, _ld);
-
-      unsigned int nf = _n*_n, ne = _n, nw = 2*_n*_n + 3*_n;
-      _odwork = tmalloc(double, 6*nf + 9*ne + nw);
-      _glpoints = tmalloc (double, 3*nf);
-    }
-
-    void SpectralQuad::freedata()
-    {
-      for(int d=0; d<2; d++){
-        free(_z[d]);
-        lagrange_free(&_ld[d]);
-      }
-      opt_free_2(&_data);
-      free(_odwork);
-      free(_glpoints);
-    }
-
-    void SpectralQuad::set_gl_points( double * x, double * y, double *z)
-    {
-      _xyz[0] = x;
-      _xyz[1] = y;
-      _xyz[2] = z;
-    }
-    CartVect SpectralQuad::evaluate( const CartVect& params ) const
-    {
-        //piece that we shouldn't want to cache
-      int d=0;
-      for(d=0; d<2; d++){
-        lagrange_0(&_ld[d], params[d]);
-      }
-      CartVect result;
-      for (d=0; d<3; d++)
-      {
-        result[d] = tensor_i2(_ld[0].J,_ld[0].n,
-                              _ld[1].J,_ld[1].n,
-                              _xyz[d],
-                              _odwork);
-      }
-      return result;
-    }
-      // replicate the functionality of hex_findpt
-    bool SpectralQuad::evaluate_reverse(CartVect const & xyz, CartVect &params, double tol, const CartVect &init) const
-    {
-      params = init;
-
-        //find nearest point
-      double x_star[3];
-      xyz.get(x_star);
-
-      double r[2] = {0, 0 }; // initial guess for parametric coords
-      unsigned c = opt_no_constraints_3;
-      double dist = opt_findpt_2(&_data, (const double **)_xyz, x_star, r, &c);
-        // if it did not converge, get out with throw...
-      if (dist > 0.9e+30)
-        throw Map::EvaluationError();
-        //c tells us if we landed inside the element or exactly on a face, edge, or node
-        // also, dist shows the distance to the computed point.
-        //copy parametric coords back
-      params = r;
-
-      return is_inside(params, tol);
-    }
-
-
-    Matrix3  SpectralQuad::jacobian(const CartVect& /*params*/) const
-    {
-        // not implemented
-      Matrix3 J(0.);
-      return J;
-    }
-
-
-    void SpectralQuad::evaluate_vector(const CartVect& params, const double *field, int num_tuples, double *eval) const
-    {
-        //piece that we shouldn't want to cache
-      int d;
-      for(d=0; d<2; d++){
-        lagrange_0(&_ld[d], params[d]);
-      }
-
-      *eval = tensor_i2(_ld[0].J,_ld[0].n,
-                        _ld[1].J,_ld[1].n,
-                        field,
-                        _odwork);
-    }
-    void SpectralQuad:: integrate_vector(const double */*field_values*/, int /*num_tuples*/, double */*integral*/) const
-    {
-      // not implemented
-    }
-      // this is the same as a linear hex, although we should not need it
-    bool SpectralQuad::is_inside(const CartVect & params, double tol) const
-    {
-        // just look at the box+tol here
-      return ( params[0]>=-1.-tol) && (params[0]<=1.+tol) &&
-          ( params[1]>=-1.-tol) && (params[1]<=1.+tol) ;
-    }
-      // something we don't do for spectral hex; we do it here because
-      //       we do not store the position of gl points in a tag yet
-    void SpectralQuad::compute_gl_positions()
-    {
-        // will need to use shape functions on a simple linear quad to compute gl points
-        // so we know the position of gl points in parametric space, we will just compute those
-        // from the 3d vertex position (corner nodes of the quad), using simple mapping
-      assert (this->vertex.size()==4);
-      static double corner_params[4][2]={ { -1., -1.},
-                                          {  1., -1.},
-                                          {  1.,  1.},
-                                          { -1.,  1.} };
-        // we will use the cached lobatto nodes in parametric space _z[d] (the same in both directions)
-      int indexGL=0;
-      int n2= _n*_n;
-      for (int i=0; i<_n; i++)
-      {
-        double csi=_z[0][i];
-        for (int j=0; j<_n; j++)
-        {
-          double eta = _z[1][j]; // we could really use the same _z[0] array of lobatto nodes
-          CartVect pos(0.0);
-          for (int k = 0; k < 4; k++) {
-            const double N_k = (1 + csi*corner_params[k][0])
-                * (1 + eta*corner_params[k][1]);
-            pos += N_k * vertex[k];
-          }
-          pos *= 0.25;// these are x, y, z of gl points; reorder them
-          _glpoints[indexGL] = pos[0]; // x
-          _glpoints[indexGL+n2] = pos[1]; // y
-          _glpoints[indexGL+2*n2] = pos[2]; // z
-          indexGL++;
-        }
-      }
-        // now, we can set the _xyz pointers to internal memory allocated to these!
-      _xyz[0] =  &(_glpoints[0]);
-      _xyz[1] =  &(_glpoints[n2]);
-      _xyz[2] =  &(_glpoints[2*n2]);
-    }
-    void SpectralQuad::get_gl_points( double *& x, double *& y, double *& z, int & size)
-    {
-      x=  (double *)_xyz[0] ;
-      y = (double *)_xyz[1] ;
-      z = (double *)_xyz[2] ;
-      size = _n*_n;
-    }
-    
-}// namespace Element
-
-} // namespace moab

diff --git a/src/LocalDiscretization/moab/SpectralFuncs.hpp b/src/LocalDiscretization/moab/SpectralFuncs.hpp
new file mode 100644
index 0000000..e0eddf5
--- /dev/null
+++ b/src/LocalDiscretization/moab/SpectralFuncs.hpp
@@ -0,0 +1,481 @@
+#ifndef SPECTRALFUNCS_HPP
+#define SPECTRALFUNCS_HPP
+
+#include "float.h"
+
+//======================================================
+// from types.h
+//======================================================
+
+/* integer type to use for everything */
+#if   defined(USE_LONG)
+#  define INTEGER long
+#elif defined(USE_LONG_LONG)
+#  define INTEGER long long
+#elif defined(USE_SHORT)
+#  define INTEGER short
+#else
+#  define INTEGER int
+#endif
+
+/* when defined, use the given type for global indices instead of INTEGER */
+#if   defined(USE_GLOBAL_LONG_LONG)
+#  define GLOBAL_INT long long
+#elif defined(USE_GLOBAL_LONG)
+#  define GLOBAL_INT long
+#else
+#  define GLOBAL_INT long
+#endif
+
+/* floating point type to use for everything */
+#if   defined(USE_FLOAT)
+   typedef float real;
+#  define floorr floorf
+#  define ceilr  ceilf
+#  define sqrtr  sqrtf
+#  define fabsr  fabsf
+#  define cosr   cosf
+#  define sinr   sinf
+#  define EPS   (128*FLT_EPSILON)
+#  define PI 3.1415926535897932384626433832795028841971693993751058209749445923F
+#elif defined(USE_LONG_DOUBLE)
+   typedef long double real;
+#  define floorr floorl
+#  define ceilr  ceill
+#  define sqrtr  sqrtl
+#  define fabsr  fabsl
+#  define cosr   cosl
+#  define sinr   sinl
+#  define EPS   (128*LDBL_EPSILON)
+#  define PI 3.1415926535897932384626433832795028841971693993751058209749445923L
+#else
+   typedef double real;
+#  define floorr floor
+#  define ceilr  ceil
+#  define sqrtr  sqrt
+#  define fabsr  fabs
+#  define cosr   cos
+#  define sinr   sin
+#  define EPS   (128*DBL_EPSILON)
+#  define PI 3.1415926535897932384626433832795028841971693993751058209749445923
+#endif
+
+/* apparently uint and ulong can be defined already in standard headers */
+#define uint uint_
+#define ulong ulong_
+#define sint sint_
+#define slong slong_
+
+typedef   signed INTEGER sint;
+typedef unsigned INTEGER uint;
+#undef INTEGER
+
+#ifdef GLOBAL_INT
+  typedef   signed GLOBAL_INT slong;
+  typedef unsigned GLOBAL_INT ulong;
+#else
+  typedef sint slong;
+  typedef uint ulong;
+#endif
+
+//======================================================
+// from poly.h
+//======================================================
+
+/* 
+  For brevity's sake, some names have been shortened
+  Quadrature rules
+    Gauss   -> Gauss-Legendre quadrature (open)
+    Lobatto -> Gauss-Lobatto-Legendre quadrature (closed at both ends)
+  Polynomial bases
+    Legendre -> Legendre basis
+    Gauss    -> Lagrangian basis using Gauss   quadrature nodes
+    Lobatto  -> Lagrangian basis using Lobatto quadrature nodes
+*/
+
+/*--------------------------------------------------------------------------
+   Legendre Polynomial Matrix Computation
+   (compute P_i(x_j) for i = 0, ..., n and a given set of x)
+  --------------------------------------------------------------------------*/
+
+/* precondition: n >= 1
+   inner index is x index (0 ... m-1);
+   outer index is Legendre polynomial number (0 ... n)
+ */
+void legendre_matrix(const real *x, int m, real *P, int n);
+
+/* precondition: n >= 1
+   inner index is Legendre polynomial number (0 ... n)
+   outer index is x index (0 ... m-1);
+ */
+void legendre_matrix_t(const real *x, int m, real *P, int n);
+
+/* precondition: n >= 1
+   compute P_i(x) with i = 0 ... n
+ */
+void legendre_row(real x, real *P, int n);
+
+
+/*--------------------------------------------------------------------------
+   Quadrature Nodes and Weights Calculation
+   
+   call the _nodes function before calling the _weights function
+  --------------------------------------------------------------------------*/
+
+void gauss_nodes(real *z, int n);   /* n nodes (order = 2n-1) */
+void lobatto_nodes(real *z, int n); /* n nodes (order = 2n-3) */
+
+void gauss_weights(const real *z, real *w, int n);
+void lobatto_weights(const real *z, real *w, int n);
+
+/*--------------------------------------------------------------------------
+   Lagrangian to Legendre Change-of-basis Matrix
+  --------------------------------------------------------------------------*/
+
+/* precondition: n >= 2
+   given the Gauss quadrature rule (z,w,n), compute the square matrix J
+   for transforming from the Gauss basis to the Legendre basis:
+   
+      u_legendre(i) = sum_j J(i,j) u_gauss(j)
+
+   computes J   = .5 (2i+1) w  P (z )
+             ij              j  i  j
+             
+   in column major format (inner index is i, the Legendre index)
+ */
+void gauss_to_legendre(const real *z, const real *w, int n, real *J);
+
+/* precondition: n >= 2
+   same as above, but
+   in row major format (inner index is j, the Gauss index)
+ */
+void gauss_to_legendre_t(const real *z, const real *w, int n, real *J);
+
+/* precondition: n >= 3
+   given the Lobatto quadrature rule (z,w,n), compute the square matrix J
+   for transforming from the Lobatto basis to the Legendre basis:
+   
+      u_legendre(i) = sum_j J(i,j) u_lobatto(j)
+
+   in column major format (inner index is i, the Legendre index)
+ */
+void lobatto_to_legendre(const real *z, const real *w, int n, real *J);
+
+/*--------------------------------------------------------------------------
+   Lagrangian basis function evaluation
+  --------------------------------------------------------------------------*/
+
+/* given the Lagrangian nodes (z,n) and evaluation points (x,m)
+   evaluate all Lagrangian basis functions at all points x
+   
+   inner index of output J is the basis function index (row-major format)
+   provide work array with space for 4*n doubles
+ */
+void lagrange_weights(const real *z, unsigned n,
+                      const real *x, unsigned m,
+                      real *J, real *work);
+
+/* given the Lagrangian nodes (z,n) and evaluation points (x,m)
+   evaluate all Lagrangian basis functions and their derivatives
+   
+   inner index of outputs J,D is the basis function index (row-major format)
+   provide work array with space for 6*n doubles
+ */
+void lagrange_weights_deriv(const real *z, unsigned n,
+                            const real *x, unsigned m,
+                            real *J, real *D, real *work);
+
+/*--------------------------------------------------------------------------
+   Speedy Lagrangian Interpolation
+   
+   Usage:
+   
+     lagrange_data p;
+     lagrange_setup(&p,z,n);    *  setup for nodes z[0 ... n-1] *
+     
+     the weights
+       p->J [0 ... n-1]     interpolation weights
+       p->D [0 ... n-1]     1st derivative weights
+       p->D2[0 ... n-1]     2nd derivative weights
+     are computed for a given x with:
+       lagrange_0(p,x);  *  compute p->J *
+       lagrange_1(p,x);  *  compute p->J, p->D *
+       lagrange_2(p,x);  *  compute p->J, p->D, p->D2 *
+       lagrange_2u(p);   *  compute p->D2 after call of lagrange_1(p,x); *
+     These functions use the z array supplied to setup
+       (that pointer should not be freed between calls)
+     Weights for x=z[0] and x=z[n-1] are computed during setup; access as:
+       p->J_z0, etc. and p->J_zn, etc.
+
+     lagrange_free(&p);  *  deallocate memory allocated by setup *
+  --------------------------------------------------------------------------*/
+
+typedef struct {
+  unsigned n;                /* number of Lagrange nodes            */
+  const real *z;             /* Lagrange nodes (user-supplied)      */
+  real *J, *D, *D2;          /* weights for 0th,1st,2nd derivatives */
+  real *J_z0, *D_z0, *D2_z0; /* ditto at z[0]   (computed at setup) */
+  real *J_zn, *D_zn, *D2_zn; /* ditto at z[n-1] (computed at setup) */
+  real *w, *d, *u0, *v0, *u1, *v1, *u2, *v2; /* work data           */
+} lagrange_data;
+
+void lagrange_setup(lagrange_data *p, const real *z, unsigned n);
+void lagrange_free(lagrange_data *p);
+
+void lagrange_0(lagrange_data *p, real x) ;
+void lagrange_1(lagrange_data *p, real x) ;
+void lagrange_2(lagrange_data *p, real x) ;
+void lagrange_2u(lagrange_data *p) ;
+
+//======================================================
+// from tensor.h
+//======================================================
+
+/*--------------------------------------------------------------------------
+   1-,2-,3-d Tensor Application
+   
+   the 3d case:
+   tensor_f3(R,mr,nr, S,ms,ns, T,mt,nt, u,v, work1,work2)
+     gives v = [ R (x) S (x) T ] u
+     where R is mr x nr, S is ms x ns, T is mt x nt,
+       each in row- or column-major format according to f := r | c
+     u is nr x ns x nt in column-major format (inner index is r)
+     v is mr x ms x mt in column-major format (inner index is r)
+  --------------------------------------------------------------------------*/
+
+void tensor_c1(const real *R, unsigned mr, unsigned nr, 
+               const real *u, real *v);
+void tensor_r1(const real *R, unsigned mr, unsigned nr, 
+               const real *u, real *v);
+
+/* work holds mr*ns reals */
+void tensor_c2(const real *R, unsigned mr, unsigned nr,
+               const real *S, unsigned ms, unsigned ns,
+               const real *u, real *v, real *work);
+void tensor_r2(const real *R, unsigned mr, unsigned nr,
+               const real *S, unsigned ms, unsigned ns,
+               const real *u, real *v, real *work);
+
+/* work1 holds mr*ns*nt reals,
+   work2 holds mr*ms*nt reals */
+void tensor_c3(const real *R, unsigned mr, unsigned nr,
+               const real *S, unsigned ms, unsigned ns,
+               const real *T, unsigned mt, unsigned nt,
+               const real *u, real *v, real *work1, real *work2);
+void tensor_r3(const real *R, unsigned mr, unsigned nr,
+               const real *S, unsigned ms, unsigned ns,
+               const real *T, unsigned mt, unsigned nt,
+               const real *u, real *v, real *work1, real *work2);
+
+/*--------------------------------------------------------------------------
+   1-,2-,3-d Tensor Application of Row Vectors (for Interpolation)
+   
+   the 3d case:
+   v = tensor_i3(Jr,nr, Js,ns, Jt,nt, u, work)
+   same effect as tensor_r3(Jr,1,nr, Js,1,ns, Jt,1,nt, u,&v, work1,work2):
+     gives v = [ Jr (x) Js (x) Jt ] u
+     where Jr, Js, Jt are row vectors (interpolation weights)
+     u is nr x ns x nt in column-major format (inner index is r)
+     v is a scalar
+  --------------------------------------------------------------------------*/
+
+real tensor_i1(const real *Jr, unsigned nr, const real *u);
+
+/* work holds ns reals */
+real tensor_i2(const real *Jr, unsigned nr,
+               const real *Js, unsigned ns,
+               const real *u, real *work);
+
+/* work holds ns*nt + nt reals */
+real tensor_i3(const real *Jr, unsigned nr,
+               const real *Js, unsigned ns,
+               const real *Jt, unsigned nt,
+               const real *u, real *work);
+
+/*--------------------------------------------------------------------------
+   1-,2-,3-d Tensor Application of Row Vectors
+             for simultaneous Interpolation and Gradient computation
+   
+   the 3d case:
+   v = tensor_ig3(Jr,Dr,nr, Js,Ds,ns, Jt,Dt,nt, u,g, work)
+     gives v   = [ Jr (x) Js (x) Jt ] u
+           g_0 = [ Dr (x) Js (x) Jt ] u
+           g_1 = [ Jr (x) Ds (x) Jt ] u
+           g_2 = [ Jr (x) Js (x) Dt ] u
+     where Jr,Dr,Js,Ds,Jt,Dt are row vectors
+       (interpolation & derivative weights)
+     u is nr x ns x nt in column-major format (inner index is r)
+     v is a scalar, g is an array of 3 reals
+  --------------------------------------------------------------------------*/
+
+real tensor_ig1(const real *Jr, const real *Dr, unsigned nr,
+                const real *u, real *g);
+
+/* work holds 2*ns reals */
+real tensor_ig2(const real *Jr, const real *Dr, unsigned nr,
+                const real *Js, const real *Ds, unsigned ns,
+                const real *u, real *g, real *work);
+
+/* work holds 2*ns*nt + 3*ns reals */
+real tensor_ig3(const real *Jr, const real *Dr, unsigned nr,
+                const real *Js, const real *Ds, unsigned ns,
+                const real *Jt, const real *Dt, unsigned nt,
+                const real *u, real *g, real *work);
+
+//======================================================
+// from findpt.h
+//======================================================
+
+typedef struct {
+  const real *xw[2];   /* geometry data */
+  real *z[2];          /* lobatto nodes */
+  lagrange_data ld[2]; /* interpolation, derivative weights & data */
+  unsigned nptel;      /* nodes per element */
+  struct findpt_hash_data_2 *hash;   /* geometric hashing data */
+  struct findpt_listel *list, **sorted, **end;
+                                        /* pre-allocated list of elements to
+                                           check (found by hashing), and
+                                           pre-allocated list of pointers into
+                                           the first list for sorting */
+  struct findpt_opt_data_2 *od; /* data for the optimization algorithm */
+  real *od_work;
+} findpt_data_2;
+
+typedef struct {
+  const real *xw[3];   /* geometry data */
+  real *z[3];          /* lobatto nodes */
+  lagrange_data ld[3]; /* interpolation, derivative weights & data */
+  unsigned nptel;      /* nodes per element */
+  struct findpt_hash_data_3 *hash;   /* geometric hashing data */
+  struct findpt_listel *list, **sorted, **end;
+                                        /* pre-allocated list of elements to
+                                           check (found by hashing), and
+                                           pre-allocated list of pointers into
+                                           the first list for sorting */
+  struct findpt_opt_data_3 *od; /* data for the optimization algorithm */
+  real *od_work;
+} findpt_data_3;
+
+findpt_data_2 *findpt_setup_2(
+          const real *const xw[2], const unsigned n[2], uint nel,
+          uint max_hash_size, real bbox_tol);
+findpt_data_3 *findpt_setup_3(
+          const real *const xw[3], const unsigned n[3], uint nel,
+          uint max_hash_size, real bbox_tol);
+
+void findpt_free_2(findpt_data_2 *p);
+void findpt_free_3(findpt_data_3 *p);
+
+const real *findpt_allbnd_2(const findpt_data_2 *p);
+const real *findpt_allbnd_3(const findpt_data_3 *p);
+
+typedef int (*findpt_func)(void *, const real *, int, uint *, real *, real *);
+int findpt_2(findpt_data_2 *p, const real x[2], int guess,
+             uint *el, real r[2], real *dist);
+int findpt_3(findpt_data_3 *p, const real x[3], int guess,
+             uint *el, real r[3], real *dist);
+
+inline void findpt_weights_2(findpt_data_2 *p, const real r[2])
+{
+  lagrange_0(&p->ld[0],r[0]);
+  lagrange_0(&p->ld[1],r[1]);
+}
+
+inline void findpt_weights_3(findpt_data_3 *p, const real r[3])
+{
+  lagrange_0(&p->ld[0],r[0]);
+  lagrange_0(&p->ld[1],r[1]);
+  lagrange_0(&p->ld[2],r[2]);
+}
+
+inline double findpt_eval_2(findpt_data_2 *p, const real *u)
+{
+  return tensor_i2(p->ld[0].J,p->ld[0].n,
+                   p->ld[1].J,p->ld[1].n,
+                   u, p->od_work);
+}
+
+inline double findpt_eval_3(findpt_data_3 *p, const real *u)
+{
+  return tensor_i3(p->ld[0].J,p->ld[0].n,
+                   p->ld[1].J,p->ld[1].n,
+                   p->ld[2].J,p->ld[2].n,
+                   u, p->od_work);
+}
+
+//======================================================
+// from extrafindpt.h
+//======================================================
+
+typedef struct {
+  unsigned constraints;
+  unsigned dn, d1, d2;
+  real *x[3], *fdn[3];
+} opt_face_data_3;
+
+typedef struct {
+  unsigned constraints;
+  unsigned de, d1, d2;
+  real *x[3], *fd1[3], *fd2[3];
+} opt_edge_data_3;
+
+typedef struct {
+  unsigned constraints;
+  real x[3], jac[9];
+} opt_point_data_3;
+
+typedef struct {
+  lagrange_data *ld;
+  unsigned size[4];
+  const real *elx[3];
+  opt_face_data_3 fd;
+  opt_edge_data_3 ed;
+  opt_point_data_3 pd;
+  real *work;
+  real x[3], jac[9];
+} opt_data_3;
+
+
+void opt_alloc_3(opt_data_3 *p, lagrange_data *ld);
+void opt_free_3(opt_data_3 *p);
+double opt_findpt_3(opt_data_3 *p, const real *const elx[3],
+                           const real xstar[3], real r[3], unsigned *constr);
+void opt_vol_set_intp_3(opt_data_3 *p, const real r[3]);
+
+const unsigned opt_no_constraints_2 = 3+1;
+const unsigned opt_no_constraints_3 = 9+3+1;
+
+/* for 2d spectralQuad */
+/*--------------------------------------------------------------------------
+
+   2 - D
+
+  --------------------------------------------------------------------------*/
+
+typedef struct {
+  unsigned constraints;
+  unsigned de, d1;
+  real *x[2], *fd1[2];
+} opt_edge_data_2;
+
+typedef struct {
+  unsigned constraints;
+  real x[2], jac[4];
+} opt_point_data_2;
+
+typedef struct {
+  lagrange_data *ld;
+  unsigned size[3];
+  const real *elx[2];
+  opt_edge_data_2 ed;
+  opt_point_data_2 pd;
+  real *work;
+  real x[2], jac[4];
+} opt_data_2;
+void opt_alloc_2(opt_data_2 *p, lagrange_data *ld);
+void opt_free_2(opt_data_2 *p);
+double opt_findpt_2(opt_data_2 *p, const real *const elx[2],
+                           const real xstar[2], real r[2], unsigned *constr);
+
+#endif
+

diff --git a/src/moab/ElemUtil.hpp b/src/moab/ElemUtil.hpp
deleted file mode 100644
index b56b346..0000000
--- a/src/moab/ElemUtil.hpp
+++ /dev/null
@@ -1,244 +0,0 @@
-#ifndef MOAB_ELEM_UTIL_HPP
-#define MOAB_ELEM_UTIL_HPP
-
-#include "moab/CartVect.hpp"
-#include <vector>
-#include "moab/Matrix3.hpp"
-
-// to access data structures for spectral elements
-extern "C"{
-#include "types.h"
-#include "poly.h"
-#include "tensor.h"
-#include "findpt.h"
-#include "extrafindpt.h"
-#include "errmem.h"
-}
-
-namespace moab {
-    namespace Element {
-          /**\brief Class representing a map (diffeomorphism) F parameterizing a 3D element by its canonical preimage.*/
-          /*   
-               Shape functions on the element can obtained by a pushforward (pullback by the inverse map) 
-               of the shape functions on the canonical element. This is done by extending this class.
-         
-               We further assume that the parameterizing map is defined by the location of n vertices,
-               which can be set and retrived on a Map instance.  The number of vertices is fixed at 
-               compile time.
-          */
-        class Map {
-      public:
-            /**\brief Construct a Map defined by the given std::vector of vertices. */
-          Map(const CartVect *v, int num_vs) {this->vertex.resize(num_vs); this->set_vertices(v, num_vs);};
-            /**\brief Construct a Map defined by n vertices. */
-          Map(const unsigned int n) {this->vertex = std::vector<CartVect>(n);};
-            /**\brief Evaluate the map on \params (calculate $\vec x = F($\vec \params)$ )*/
-          virtual CartVect evaluate( const CartVect& params ) const = 0;
-            /**\brief Evaluate the inverse map (calculate $\vec \params = F^-1($\vec x)$ to given tolerance)*/
-          bool evaluate_reverse( const CartVect& x, CartVect &params, double tol = 1.0e-10, const CartVect &x0 = CartVect(0.0)) const ;
-            /**\brief decide if within the natural param space, with a tolerance*/
-          virtual bool is_inside(const CartVect & params, double tol) const = 0;
-            /* FIX: should evaluate and ievaluate return both the value and the Jacobian (first jet)? */
-            /**\brief Evaluate the map's Jacobi matrix. */
-          virtual Matrix3 jacobian( const CartVect& params ) const = 0;
-            /* FIX: should this be evaluated in real coordinates and be obtained as part of a Newton solve? */
-          virtual Matrix3 jacobian_inverse(const CartVect& params) {return jacobian(params).inverse();}
-            /**\brief Evaluate the determinate of the Jacobi matrix. */
-          virtual double  det_jacobian(const CartVect& params) const {return this->jacobian(params).determinant();};
-            /* FIX: should this be evaluated in real coordinates and be obtained as part of a Newton solve? */
-            /**\brief Evaluate the determinate of the inverse Jacobi matrix. */
-          virtual double  det_jacobian_inverse(const CartVect& params) const {return this->jacobian(params).inverse().determinant();};
-            /**\brief Evaluate a scalar field at a point given field values at the vertices. */
-          virtual double evaluate_scalar(const CartVect& params, const double *field_values) const 
-              {double tmp; evaluate_vector(params, field_values, 1, &tmp); return tmp;}
-            /**\brief Integrate a scalar field over the element given field values at the vertices. */
-          virtual double integrate_scalar(const double *field_values) const
-              {double tmp; integrate_vector(field_values, 1, &tmp); return tmp;}
-            /**\brief Evaluate a vector field of n tuples at a point given interleaved values at the vertices. */
-          virtual void evaluate_vector(const CartVect& params, const double *field_values, int num_tuples, double *eval) const = 0;
-            /**\brief Integrate a vector field of n tuples over the element given interleaved values at the vertices. */
-          virtual void integrate_vector(const double *field_values, int num_tuples, double *integral) const = 0;
-
-            /**\brief Size of the vertices vector. */
-          unsigned int num_verts() {return this->vertex.size();}
-            /**\brief Retrieve vertices. */
-          inline const std::vector<CartVect>& get_vertices();
-            /**\brief Set vertices.      */
-          virtual void set_vertices(const CartVect *v, int num_vs);
-      
-            /* Exception thrown when an evaluation fails (e.g., ievaluate fails to converge). */
-          class EvaluationError {
-        public:
-            EvaluationError(){};
-          };// class EvaluationError
-      
-            /* Exception thrown when a bad argument is encountered. */
-          class ArgError {
-        public:
-            ArgError(){};
-          };// class ArgError
-      protected:
-          std::vector<CartVect> vertex;
-        };// class Map
-
-          /**\brief Shape function space for trilinear hexahedron, obtained by a pushforward of the canonical linear (affine) functions. */
-        class LinearHex : public Map {
-      public:
-          LinearHex(const CartVect *vertices, int num_vs) : Map(vertices, num_vs){};
-          LinearHex() : Map(0) {}
-          virtual CartVect evaluate( const CartVect& params ) const;
-          virtual bool is_inside(const CartVect &params, double tol) const;
-
-          virtual Matrix3 jacobian(const CartVect& params) const;
-          void evaluate_vector(const CartVect& params, const double *field_vertex_values, int num_tuples, double *eval) const;
-          void integrate_vector(const double *field_vertex_values, int num_tuples, double *integral) const;
-
-      protected:
-            /* Preimages of the vertices -- "canonical vertices" -- are known as "corners". */
-          static const double corner[8][3];
-          static const double gauss[1][2];
-          static const unsigned int corner_count = 8;
-          static const unsigned int gauss_count  = 1;
-      
-        };// class LinearHex
-
-          /**\brief Shape function space for trilinear hexahedron, obtained by a pushforward of the canonical linear (affine) functions. */
-        class QuadraticHex : public Map {
-      public:
-          QuadraticHex(const CartVect *vertices, int num_vs) : Map(vertices, num_vs){};
-          QuadraticHex();
-          virtual CartVect evaluate( const CartVect& params ) const;
-          virtual bool is_inside(const CartVect &params, double tol) const;
-
-          virtual Matrix3 jacobian(const CartVect& params) const;
-          void evaluate_vector(const CartVect& params, const double *field_values, int num_tuples, double *eval) const;
-          void integrate_vector(const double *field_values, int num_tuples, double *integral) const;
-
-      protected:
-            /* Preimages of the vertices -- "canonical vertices" -- are known as "corners".
-             * there are 27 vertices for a tri-quadratic xes*/
-          static const int corner[27][3];
-          static const double gauss[8][2];// TODO fix me
-          static const unsigned int corner_count = 27;
-          static const unsigned int gauss_count  = 8; // TODO fix me
-
-        };// class LinearHex
-          /**\brief Shape function space for a linear tetrahedron, obtained by a pushforward of the canonical affine shape functions. */
-        class LinearTet : public Map {
-      public:
-          LinearTet(const CartVect *vertices, int num_vs) : Map(vertices, num_vs){};
-          LinearTet();
-            /* Override the evaluation routines to take advantage of the properties of P1. */
-          virtual CartVect evaluate(const CartVect& params) const {return this->vertex[0] + this->T*params;};
-          virtual bool evaluate_reverse(const CartVect& x, CartVect &params, double tol = 1.0e-10, const CartVect& = CartVect(0.0)) const {params = this->T_inverse*(x-this->vertex[0]); return is_inside(params, tol);};
-          virtual Matrix3  jacobian(const CartVect&)  const {return this->T;};
-          virtual Matrix3  jacobian_inverse(const CartVect&) const {return this->T_inverse;};
-          virtual double   det_jacobian(const CartVect&)  const {return this->det_T;};
-          virtual double   det_jacobian_inverse(const CartVect&) const {return this->det_T_inverse;};
-            //
-          void evaluate_vector(const CartVect& params, const double *field_values, int num_tuples, double *eval) const;
-          void integrate_vector(const double *field_vertex_values, int num_tuples, double *integral) const;
-            //
-            /* Override set_vertices so we can precompute the matrices effecting the mapping to and from the canonical simplex. */
-          void set_vertices(const CartVect *v, int num_vs);
-          bool is_inside(const CartVect &params, double tol) const;
-      protected:
-          static const double corner[4][3];
-          Matrix3 T, T_inverse;
-          double  det_T, det_T_inverse;
-        };// class LinearTet
-    
-        class SpectralHex : public Map {
-      public:
-          SpectralHex(const CartVect *vertices, int num_vs) : Map(vertices, num_vs){};
-          SpectralHex(int order, double * x, double * y, double *z) ;
-          SpectralHex(int order);
-          SpectralHex();
-          virtual ~SpectralHex();
-          void set_gl_points( double * x, double * y, double *z) ;
-          virtual CartVect evaluate( const CartVect& params ) const;
-          virtual bool evaluate_reverse(const CartVect& x, CartVect &params, double tol = 1.0e-10, const CartVect &init = CartVect(0.0)) const;
-          virtual Matrix3  jacobian(const CartVect& params) const;
-          void evaluate_vector(const CartVect& params, const double *field_values, int num_tuples, double *eval) const;
-          void integrate_vector(const double *field_values, int num_tuples, double *integral) const;
-          bool is_inside(const CartVect &params, double tol) const;
-
-            // to compute the values that need to be cached for each element of order n
-          void Init(int order);
-          void freedata();
-      protected:
-            /* values that depend only on the order of the element , cached */
-            /*  the order in 3 directions */
-          static int _n;
-          static real *_z[3];
-          static lagrange_data _ld[3];
-          static opt_data_3 _data;
-          static real * _odwork;// work area
-// flag for initialization of data
-          static bool _init;
-
-          real * _xyz[3];
-
-
-        };// class SpectralHex
-
-        class SpectralQuad : public Map {
-      public:
-          SpectralQuad(const CartVect *vertices, int num_vs) : Map(vertices, num_vs){};
-          SpectralQuad(int order, double * x, double * y, double *z) ;
-          SpectralQuad(int order);
-          SpectralQuad();
-          virtual ~SpectralQuad();
-          void set_gl_points( double * x, double * y, double *z) ;
-          virtual CartVect evaluate( const CartVect& params ) const;// a 2d, so 3rd component is 0, always
-          virtual bool evaluate_reverse(const CartVect& x, CartVect &params, double tol = 1.0e-10, const CartVect &x0 = CartVect(0.0)) const; //a 2d, so 3rd component is 0, always
-          virtual Matrix3  jacobian(const CartVect& params) const;
-          void evaluate_vector(const CartVect& params, const double *field_vertex_values, int num_tuples, double *eval) const;
-          void integrate_vector(const double *field_vertex_values, int num_tuples, double *integral) const;
-          bool is_inside(const CartVect &params, double tol) const;
-
-            // to compute the values that need to be cached for each element of order n
-          void Init(int order);
-          void freedata();
-            // this will take node, vertex positions and compute the gl points
-          void compute_gl_positions();
-          void get_gl_points(  double *& x, double *& y, double *& z, int & size) ;
-      protected:
-            /* values that depend only on the order of the element , cached */
-            /*  the order in all 3 directions ; it is also np in HOMME lingo*/
-          static int _n;
-          static real *_z[2];
-          static lagrange_data _ld[2];
-          static opt_data_2 _data; // we should use only 2nd component
-          static real * _odwork;// work area
-
-            // flag for initialization of data
-          static bool _init;
-          static real * _glpoints; // it is a space we can use to store gl positions for elements
-            // on the fly; we do not have a tag yet for them, as in Nek5000 application
-            // also, these positions might need to be moved on the sphere, for HOMME grids
-            // do we project them or how do we move them on the sphere?
-
-          real * _xyz[3]; // these are gl points; position?
-
-
-        };// class SpectralQuad
-
-
-  inline const std::vector<CartVect>& Map::get_vertices() {
-    return this->vertex;
-  }
-  //
-        inline void Map::set_vertices(const CartVect *v, int num_vs) {
-          if(num_vs != (int)this->vertex.size()) {
-      throw ArgError();
-    }
-          std::copy(v, v+num_vs, this->vertex.begin());
-  }// Map::set_vertices()
-
-
-    }// namespace Element
- 
-} // namespace moab
-
-#endif /*MOAB_ELEM_UTIL_HPP*/

diff --git a/test/perf/point_in_elem.cpp b/test/perf/point_in_elem.cpp
deleted file mode 100644
index 6a90ec0..0000000
--- a/test/perf/point_in_elem.cpp
+++ /dev/null
@@ -1,346 +0,0 @@
-#include "moab/Core.hpp"
-#include "moab/AdaptiveKDTree.hpp"
-#include "moab/Range.hpp"
-#include "moab/CartVect.hpp"
-#include "moab/GeomUtil.hpp"
-#include <iostream>
-#include <time.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <sstream>
-
-#define CHK(ErrorCode) do { if (MB_SUCCESS != (ErrorCode)) fail( (ErrorCode), __FILE__, __LINE__ ); } while(false)
-
-using namespace moab;
-
-static void fail( ErrorCode error_code, const char* file_name, int line_number );
-
-enum TreeType {  UseKDTree, UseNoTree, UseDefaultTree = UseKDTree };
-
-const char* default_str = "(default)";
-const char* empty_str = "";
-inline const char* is_default_tree( TreeType type ) {
-  return type == UseDefaultTree ? default_str : empty_str;
-}
-
-const long DEFAULT_NUM_TEST = 100000;
-const long HARD_MAX_UNIQUE_POINTS = 100000;
-const long HARD_MIN_UNIQUE_POINTS = 1000;
-const long FRACTION_UNIQUE_POINTS = 100;
-
-static void usage( char* argv0, bool help = false )
-{
-  const char* usage_str = "[-k|-v] [-n <N>] [-d <N>] [-e <N>] <input_mesh>";
-  if (!help) {
-    std::cerr << "Usage: " << argv0 << " " << usage_str << std::endl;
-    std::cerr << "     : " << argv0 << " -h" << std::endl;
-    exit(1);
-  }
-  
-  std::cout << "Usage: " << argv0 << " " << usage_str << std::endl
-            << "  -k : Use kD Tree " << is_default_tree(UseKDTree) << std::endl
-            << "  -v : Use no tree" << is_default_tree(UseNoTree) << std::endl
-            << "  -n : Specify number of test points (default = " << DEFAULT_NUM_TEST << ")" << std::endl
-            << "  -d : Specify maximum tree depth" << std::endl
-            << "  -e : Specify maximum elements per leaf" << std::endl
-            << " <input_mesh> : Mesh to build and query." << std::endl
-            << std::endl;
-  exit(0);
-}
-
-static void generate_random_points( Interface& mesh, size_t num_points,
-                                    std::vector<CartVect>& points,
-                                    std::vector<EntityHandle>& point_elems );
-
-static void do_kdtree_test( Interface& mesh, int tree_depth, int elem_per_leaf,
-                            long num_test, const std::vector<CartVect>& points,
-                            std::vector<EntityHandle>& point_elems,
-                            clock_t& build_time, clock_t& test_time, size_t& depth );
-
-static void do_linear_test( Interface& mesh, int tree_depth, int elem_per_leaf,
-                            long num_test, const std::vector<CartVect>& points,
-                            std::vector<EntityHandle>& point_elems,
-                            clock_t& build_time, clock_t& test_time, size_t& depth );
-
-int main( int argc, char* argv[] )
-{
-  const char* input_file = 0;
-  long tree_depth = -1;
-  long elem_per_leaf = -1;
-  long num_points = DEFAULT_NUM_TEST;
-  TreeType type = UseDefaultTree;
-  char* endptr;
-  
-    // PARSE ARGUMENTS
-    
-  long* valptr = 0;
-  for (int i = 1; i < argc; ++i) {
-    if (valptr) {
-      *valptr = strtol( argv[i], &endptr, 0 );
-      if (*valptr < 1 || *endptr) {
-        std::cerr << "Invalid value for '" << argv[i-1] << "' flag: " << argv[i] << std::endl;
-        exit(1);
-      }
-      valptr = 0;
-    }
-    else if (argv[i][0] == '-' && argv[i][1] && !argv[i][2]) {
-      switch (argv[i][1]) {
-        case 'h': usage(argv[0],true); break;
-        case 'k': type = UseKDTree; break;
-        case 'v': type = UseNoTree; break;
-        case 'd': valptr = &tree_depth; break;
-        case 'e': valptr = &elem_per_leaf; break;
-        case 'n': valptr = &num_points; break; 
-        default:
-          std::cerr << "Invalid flag: " << argv[i] << std::endl;
-          usage(argv[0]);
-          break;
-      }
-    }
-    else if (!input_file) {
-      input_file = argv[i];
-    }
-    else {
-      std::cerr << "Unexpected argument: " << argv[i] << std::endl;
-      usage(argv[0]);
-    }
-  }
-  if (valptr) {
-    std::cerr << "Expected value following '" << argv[argc-1] << "' flag" << std::endl;
-    usage(argv[0]);
-  }
-  if (!input_file) {
-    std::cerr << "No input file specified." << std::endl;
-    usage(argv[0]);
-  }
-  
-    // LOAD MESH
-    
-  Core moab;
-  Interface& mb = moab;
-  ErrorCode rval;
-  std::string init_msg, msg;
-  mb.get_last_error( init_msg );
-  rval = mb.load_file( input_file );
-  if (MB_SUCCESS != rval) {
-    std::cerr << input_file << " : failed to read file." << std::endl;
-    mb.get_last_error( msg );
-    if (msg != init_msg) 
-      std::cerr << "message : " << msg << std::endl;
-  }
-  
-    // GENERATE TEST POINTS
-  
-  int num_unique = num_points / FRACTION_UNIQUE_POINTS;
-  if (num_unique > HARD_MAX_UNIQUE_POINTS)
-    num_unique = HARD_MAX_UNIQUE_POINTS;
-  else if (num_unique < HARD_MIN_UNIQUE_POINTS)
-    num_unique = num_points;
-  std::vector<CartVect> points;
-  std::vector<EntityHandle> elems;
-  generate_random_points( mb, num_unique, points, elems );
-  
-    // GET MEMORY USE BEFORE BUILDING TREE
-  
-  unsigned long init_total_storage;
-  mb.estimated_memory_use( 0, 0, &init_total_storage );
-  
-    // RUN TIMING TEST
-  clock_t build_time, test_time;
-  size_t actual_depth;
-  std::vector<EntityHandle> results(points.size());
-  switch (type) {
-    case UseKDTree: 
-      do_kdtree_test( mb, tree_depth, elem_per_leaf, num_points, points, results, build_time, test_time, actual_depth );
-      break;
-    case UseNoTree: 
-      do_linear_test( mb, tree_depth, elem_per_leaf, num_points, points, results, build_time, test_time, actual_depth );
-      break;
-  }
-  
-  unsigned long fini_total_storage;
-  mb.estimated_memory_use( 0, 0, &fini_total_storage );
-  
-    // VALIDATE RESULTS
-  int fail = 0;
-  if (results != elems) {
-    std::cout << "WARNING:  Test produced invalid results" << std::endl;
-    fail = 1;
-  }
-  
-    // SUMMARIZE RESULTS
-  std::cout << "Number of test queries: " << num_points << std::endl;
-  std::cout << "Tree build time: " << ((double)build_time)/CLOCKS_PER_SEC << " seconds" << std::endl;
-  std::cout << "Total query time: " << ((double)test_time)/CLOCKS_PER_SEC << " seconds" << std::endl;
-  std::cout << "Time per query: " << ((double)test_time)/CLOCKS_PER_SEC/num_points << " seconds" << std::endl;
-  std::cout << "Tree depth: " << actual_depth << std::endl;
-  if (actual_depth)
-    std::cout << "Total query time/depth: " << ((double)test_time)/CLOCKS_PER_SEC/actual_depth << " seconds" << std::endl;
-  std::cout << std::endl;
-  std::cout << "Bytes before tree construction: " << init_total_storage << std::endl;
-  std::cout << "Bytes after tree construction: " << fini_total_storage <<std::endl;
-  std::cout << "Difference: " << fini_total_storage - init_total_storage << " bytes" << std::endl;
-  return fail;
-}
-
-
-void fail( ErrorCode error_code, const char* file, int line )
-{
-  std::cerr << "Internal error (error code " << error_code << ") at " << file << ":" << line << std::endl;
-  abort();
-}
-
-const int HexSign[8][3] = { { -1, -1, -1 },
-                            {  1, -1, -1 },
-                            {  1,  1, -1 },
-                            { -1,  1, -1 },
-                            { -1, -1,  1 },
-                            {  1, -1,  1 },
-                            {  1,  1,  1 },
-                            { -1,  1,  1 } };
-
-static CartVect random_point_in_hex( Interface& mb, EntityHandle hex )
-{
-  const double f = RAND_MAX/2;
-  CartVect xi( ((double)rand() - f)/f, 
-                 ((double)rand() - f)/f, 
-                 ((double)rand() - f)/f );
-  CartVect coords[8];
-  const EntityHandle* conn;
-  int len;
-  ErrorCode rval = mb.get_connectivity( hex, conn, len, true );
-  if (len != 8 && MB_SUCCESS != rval) {
-    std::cerr << "Invalid element" << std::endl;
-    assert(false);
-    abort();
-  }
-  rval = mb.get_coords( conn, 8, reinterpret_cast<double*>(coords) );
-  CHK(rval);
-  
-  CartVect point(0,0,0);
-  for (unsigned i = 0; i < 8; ++i) {
-    double coeff = 0.125;
-    for (unsigned j = 0; j < 3; ++j)
-      coeff *= 1 + HexSign[i][j] * xi[j];
-    point += coeff * coords[i];
-  }
-  
-  return point;
-}
-
-void generate_random_points( Interface& mb, size_t num_points,
-                             std::vector<CartVect>& points,
-                             std::vector<EntityHandle>& point_elems )
-{
-  Range elems;
-  ErrorCode rval;
-  rval = mb.get_entities_by_dimension( 0, 3, elems );
-  CHK(rval);
-  if (!elems.all_of_type(MBHEX)) {
-    std::cerr << "Warning: ignoring non-hexahedral elements." << std::endl;
-    std::pair< Range::iterator, Range::iterator > p = elems.equal_range(MBHEX);
-    elems.erase( p.second, elems.end() );
-    elems.erase( elems.begin(), p.first );
-  }
-  if (elems.empty()) {
-    std::cerr << "Input file contains no hexahedral elements." << std::endl;
-    exit(1);
-  }
-  
-  points.resize( num_points );
-  point_elems.resize( num_points );
-  const size_t num_elem = elems.size();
-  for (size_t i = 0; i < num_points; ++i) {
-    size_t offset = 0;
-    for (size_t x = num_elem; x > 0; x /= RAND_MAX)
-      offset += rand();
-    offset %= num_elem;
-    point_elems[i] = elems[offset];
-    points[i] = random_point_in_hex( mb, point_elems[i] );
-  }
-}
-
-void do_kdtree_test( Interface& mb, int tree_depth, int elem_per_leaf,
-                     long num_test, const std::vector<CartVect>& points,
-                     std::vector<EntityHandle>& point_elems,
-                     clock_t& build_time, clock_t& test_time, size_t& depth )
-{
-  ErrorCode rval;
-  clock_t init = clock();
-  AdaptiveKDTree tool( &mb );
-  EntityHandle root;
-  std::ostringstream options;
-  if (tree_depth > 0) options << "MAX_DEPTH=" << tree_depth << ";";
-  if (elem_per_leaf > 0) options << "MAX_PER_LEAF=" << elem_per_leaf << ";";
-  Range all_hexes;
-  rval = mb.get_entities_by_type( 0, MBHEX, all_hexes );
-  CHK(rval);
-  FileOptions opt(options.str().c_str());
-  rval = tool.build_tree( all_hexes, &root, &opt);
-  CHK(rval);
-  all_hexes.clear();
-  build_time = clock() - init;
-  
-  EntityHandle leaf;
-  std::vector<EntityHandle> hexes;
-  std::vector<EntityHandle>::iterator j;
-  CartVect coords[8];
-  const EntityHandle* conn;
-  int len;
-  for (long i = 0; i < num_test; ++i) {
-    const size_t idx = (size_t)i % points.size();
-    rval = tool.point_search( points[idx].array(), leaf, NULL, &root ); CHK(rval);
-    hexes.clear();
-    rval = mb.get_entities_by_handle( leaf, hexes ); CHK(rval);
-    for (j = hexes.begin(); j != hexes.end(); ++j) {
-      rval = mb.get_connectivity( *j, conn, len, true ); CHK(rval);
-      rval = mb.get_coords( conn, 8, reinterpret_cast<double*>(coords) ); CHK(rval);
-      if (GeomUtil::point_in_trilinear_hex( coords, points[idx], 1e-12 )) {
-        point_elems[idx] = *j;
-        break;
-      }
-    }
-    if (j == hexes.end())
-      point_elems[idx] = 0;
-  }
-  
-  test_time = clock() - build_time;
-  double tmp_box[3];
-  unsigned max_d;
-  tool.get_info(root, tmp_box, tmp_box, max_d);
-  depth = max_d;
-}
-
-void do_linear_test( Interface& mb, int , int ,
-                     long num_test, const std::vector<CartVect>& points,
-                     std::vector<EntityHandle>& point_elems,
-                     clock_t& build_time, clock_t& test_time, size_t& depth )
-{
-  clock_t init = clock();
-  Range hexes;
-  ErrorCode rval = mb.get_entities_by_type( 0, MBHEX, hexes );
-  CHK(rval);
-  depth = 0;
-  point_elems.resize( points.size() );
-  build_time = clock() - init;
-  
-  CartVect coords[8];
-  const EntityHandle* conn;
-  int len;
-  for (long i = 0; i < num_test; ++i) {
-    const size_t idx = (size_t)i % points.size();
-    for (Range::iterator h = hexes.begin(); h != hexes.end(); ++h) {
-      rval = mb.get_connectivity( *h, conn, len, true ); CHK(rval);
-      rval = mb.get_coords( conn, 8, reinterpret_cast<double*>(coords) ); CHK(rval);
-      if (GeomUtil::point_in_trilinear_hex( coords, points[idx], 1e-12 )) {
-        point_elems[idx] = *h;
-        break;
-      }
-    }
-  }
-  
-  test_time = clock() - build_time;
-}
-
-
-  

diff --git a/test/perf/point_location/Makefile.am b/test/perf/point_location/Makefile.am
new file mode 100644
index 0000000..d291d97
--- /dev/null
+++ b/test/perf/point_location/Makefile.am
@@ -0,0 +1,15 @@
+
+AM_CPPFLAGS += -I$(top_srcdir)/src \
+               -I$(top_srcdir)/src/io/mhdf/include \
+               -I$(top_builddir)/ \
+               -I$(top_srcdir)/src/LocalDiscretization/ \
+               -DIS_BUILDING_MB
+            
+LDADD = $(top_builddir)/src/libMOAB.la
+
+check_PROGRAMS = 
+noinst_PROGRAMS = point_location elem_eval_time
+
+point_location_SOURCES = point_location.cpp
+elem_eval_time_SOURCES = elem_eval_time.cpp
+

This diff is so big that we needed to truncate the remainder.

https://bitbucket.org/fathomteam/moab/commits/47530393a8bd/
Changeset:   47530393a8bd
Branch:      None
User:        tautges
Date:        2013-03-21 16:25:28
Summary:     Fixing bugs in various places, with a few improvements here and there for other reasons.

configure.ac: include src/LocalDiscretization in list of makefiles written
AdaptiveKDTree.cpp: proper arguments to compute_bounding_box due to changing this to static; improving comments around CandidatePlaneSet enum
Core.cpp: add functionality to list_entities to print dense tag values on entities
ElemEvaluator: add static function get_eval_set that returns proper EvalSet based on type and number of vertices; relies on new
   EvalSet::compatible() function, so each new element type can decide whether it's compatible with the input type and #verts; also commented
   hpp file; fixed but setting tagDim, so it defaults to vertices; changed a few function names for setting tag, to improve ease of use
most element types: fixed args to integrateFcn, implemented compatible(),
ElemUtil: removed implementation of this I'd placed in src, now always using the one in tools/mbcoupler/ElemUtil.
Tree: made compute_bounding_box() functions static, so they can be used more widely
test/perf/point_location/Makefile.am: adding search dirs
test/perf/point_location/elem_eval_time.cpp: starting to add calls to ElemUtil functions to compare timing
Coupler.cpp, other files in tools/mbcoupler: adding calls to new tree stuff, and improving error reporting
FindPtFuncs.h: consolidated the small includes (errmem.h, types.h, etc) into one

Affected #:  36 files

diff --git a/configure.ac b/configure.ac
index 057166e..562a8c8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1185,6 +1185,7 @@ AC_CONFIG_FILES([Makefile
                  test/dual/Makefile
                  test/obb/Makefile
                  test/perf/Makefile
+                 test/perf/point_location/Makefile
                  test/io/Makefile
                  test/parallel/Makefile
                  test/oldinc/Makefile

diff --git a/src/AdaptiveKDTree.cpp b/src/AdaptiveKDTree.cpp
index 0c2f67e..8b8f100 100644
--- a/src/AdaptiveKDTree.cpp
+++ b/src/AdaptiveKDTree.cpp
@@ -83,7 +83,7 @@ namespace moab {
       
         // calculate bounding box of elements
       CartVect bmin, bmax;
-      rval = compute_bounding_box( entities, bmin, bmax);
+      rval = compute_bounding_box( *moab(), entities, bmin, bmax);
       if (MB_SUCCESS != rval)
         return rval;
   
@@ -993,7 +993,7 @@ namespace moab {
       CartVect tmin, tmax;
       for (i = set_begin; i != elems.end(); ++i) {
         tool->tree_stats().leaf_object_tests()++;
-        rval = tool->compute_bounding_box( *i, tmin, tmax);
+        rval = tool->compute_bounding_box( *tool->moab(), *i, tmin, tmax);
         if (MB_SUCCESS != rval)
           return rval;
     

diff --git a/src/Core.cpp b/src/Core.cpp
index 7adfa4c..ffa92c9 100644
--- a/src/Core.cpp
+++ b/src/Core.cpp
@@ -2880,9 +2880,11 @@ ErrorCode Core::list_entity(const EntityHandle entity) const
   if (multiple != 0)
     std::cout << "   (MULTIPLE = " << multiple << ")" << std::endl;
 
+  result = print_entity_tags(std::string(), entity, MB_TAG_DENSE);
+  
   std::cout << std::endl;
 
-  return MB_SUCCESS;
+  return result;
 }
 
 ErrorCode Core::convert_entities( const EntityHandle meshset, 
@@ -3582,16 +3584,21 @@ void Core::print(const EntityHandle ms_handle, const char *prefix,
   }
 
     // print all sparse tags
+  print_entity_tags(indent_prefix, ms_handle, MB_TAG_SPARSE);
+}
+
+ErrorCode Core::print_entity_tags(std::string indent_prefix, const EntityHandle handle, TagType tp) const
+{
   std::vector<Tag> set_tags;
-  ErrorCode result = this->tag_get_tags_on_entity(ms_handle, set_tags);
-  std::cout << indent_prefix << "Sparse tags:" << std::endl;
+  ErrorCode result = this->tag_get_tags_on_entity(handle, set_tags);
+  std::cout << indent_prefix << (tp == MB_TAG_SPARSE ? "Sparse tags:" : "Dense tags:") << std::endl;
   indent_prefix += "  ";
   
   for (std::vector<Tag>::iterator vit = set_tags.begin(); 
        vit != set_tags.end(); vit++) {
     TagType this_type;
     result = this->tag_get_type(*vit, this_type);
-    if (MB_SUCCESS != result || MB_TAG_SPARSE != this_type) continue;
+    if (MB_SUCCESS != result || tp != this_type) continue;
     DataType this_data_type;
     result = this->tag_get_data_type(*vit, this_data_type);
     int this_size;
@@ -3606,7 +3613,7 @@ void Core::print(const EntityHandle ms_handle, const char *prefix,
     if (MB_SUCCESS != result) continue;
     switch (this_data_type) {
       case MB_TYPE_INTEGER:
-        result = this->tag_get_data(*vit, &ms_handle, 1, &int_vals[0]);
+        result = this->tag_get_data(*vit, &handle, 1, &int_vals[0]);
         if (MB_SUCCESS != result) continue;
         std::cout << indent_prefix << tag_name << " = ";
         if (this_size < 10) 
@@ -3615,7 +3622,7 @@ void Core::print(const EntityHandle ms_handle, const char *prefix,
         std::cout << std::endl;
         break;
       case MB_TYPE_DOUBLE:
-        result = this->tag_get_data(*vit, &ms_handle, 1, &dbl_vals[0]);
+        result = this->tag_get_data(*vit, &handle, 1, &dbl_vals[0]);
         if (MB_SUCCESS != result) continue;
         std::cout << indent_prefix << tag_name << " = ";
         if (this_size < 10) 
@@ -3624,7 +3631,7 @@ void Core::print(const EntityHandle ms_handle, const char *prefix,
         std::cout << std::endl;
         break;
       case MB_TYPE_HANDLE:
-        result = this->tag_get_data(*vit, &ms_handle, 1, &hdl_vals[0]);
+        result = this->tag_get_data(*vit, &handle, 1, &hdl_vals[0]);
         if (MB_SUCCESS != result) continue;
         std::cout << indent_prefix << tag_name << " = ";
         if (this_size < 10) 
@@ -3635,7 +3642,7 @@ void Core::print(const EntityHandle ms_handle, const char *prefix,
       case MB_TYPE_OPAQUE:
         if (NAME_TAG_SIZE == this_size) {
           char dum_tag[NAME_TAG_SIZE];
-          result = this->tag_get_data(*vit, &ms_handle, 1, &dum_tag);
+          result = this->tag_get_data(*vit, &handle, 1, &dum_tag);
           if (MB_SUCCESS != result) continue;
             // insert NULL just in case there isn't one
           dum_tag[NAME_TAG_SIZE-1] = '\0';
@@ -3646,6 +3653,8 @@ void Core::print(const EntityHandle ms_handle, const char *prefix,
         break;
     }
   }
+
+  return MB_SUCCESS;
 }
 
 ErrorCode Core::check_adjacencies() 

diff --git a/src/LocalDiscretization/ElemEvaluator.cpp b/src/LocalDiscretization/ElemEvaluator.cpp
index 2e71c2b..8d836d9 100644
--- a/src/LocalDiscretization/ElemEvaluator.cpp
+++ b/src/LocalDiscretization/ElemEvaluator.cpp
@@ -1,11 +1,19 @@
 #include <limits>
 
-#include "ElemEvaluator.hpp"
-#include "CartVect.hpp"
-#include "Matrix3.hpp"
+#include "moab/ElemEvaluator.hpp"
+#include "moab/CartVect.hpp"
+#include "moab/Matrix3.hpp"
 
-namespace moab { 
+// need to include eval set types here to support get_eval_set; alternative would be to have some
+// type of registration, but we'd still need static registration for the built-in types
+#include "moab/LinearQuad.hpp"
+#include "moab/LinearTet.hpp"
+#include "moab/LinearHex.hpp"
+#include "moab/QuadraticHex.hpp"
+//#include "moab/SpectralQuad.hpp"
+//#include "moab/SpectralHex.hpp"
 
+namespace moab { 
     ErrorCode EvalSet::evaluate_reverse(EvalFcn eval, JacobianFcn jacob,
                                         const double *posn, const double *verts, const int nverts, 
                                         const int ndim, const double tol, double *work, 
@@ -56,4 +64,31 @@ namespace moab {
       return MB_SUCCESS;
     }// Map::evaluate_reverse()
 
+        /** \brief Given type & #vertices, get an appropriate eval set */
+    ErrorCode EvalSet::get_eval_set(EntityType tp, unsigned int num_vertices, EvalSet &eval_set) 
+    {
+      switch (tp) {
+        case MBEDGE:
+            break;
+        case MBTRI:
+            break;
+        case MBQUAD:
+            if (LinearQuad::compatible(tp, num_vertices, eval_set)) return MB_SUCCESS;
+//            if (SpectralQuad::compatible(tp, num_vertices, eval_set)) return MB_SUCCESS;
+            break;
+        case MBTET:
+            if (LinearTet::compatible(tp, num_vertices, eval_set)) return MB_SUCCESS;
+            break;
+        case MBHEX:
+            if (LinearHex::compatible(tp, num_vertices, eval_set)) return MB_SUCCESS;
+            if (QuadraticHex::compatible(tp, num_vertices, eval_set)) return MB_SUCCESS;
+//            if (SpectralHex::compatible(tp, num_vertices, eval_set)) return MB_SUCCESS;
+            break;
+        default:
+            break;
+      }
+
+      return MB_NOT_IMPLEMENTED;
+    }
+      
 } // namespace moab

diff --git a/src/LocalDiscretization/LinearHex.cpp b/src/LocalDiscretization/LinearHex.cpp
index 54506a7..b85b4bb 100644
--- a/src/LocalDiscretization/LinearHex.cpp
+++ b/src/LocalDiscretization/LinearHex.cpp
@@ -63,8 +63,8 @@ namespace moab
       return MB_SUCCESS;
     }
 
-    ErrorCode LinearHex::integrateFcn(const double *field, const double *verts, const int nverts, const int num_tuples, 
-                                      const int ndim, double *work, double *result) 
+    ErrorCode LinearHex::integrateFcn(const double *field, const double *verts, const int nverts, const int ndim, 
+                                      const int num_tuples, double *work, double *result) 
     {
       assert(field && verts && num_tuples != -1);
       double tmp_result[8];

diff --git a/src/LocalDiscretization/LinearQuad.cpp b/src/LocalDiscretization/LinearQuad.cpp
index 7fa8f15..88fab7e 100644
--- a/src/LocalDiscretization/LinearQuad.cpp
+++ b/src/LocalDiscretization/LinearQuad.cpp
@@ -49,8 +49,8 @@ namespace moab
       return MB_SUCCESS;
     }
 
-    ErrorCode LinearQuad::integrateFcn(const double *field, const double *verts, const int nverts, const int num_tuples, 
-                                       const int ndim, double *work, double *result) {
+    ErrorCode LinearQuad::integrateFcn(const double *field, const double *verts, const int nverts, const int ndim, 
+                                       const int num_tuples, double *work, double *result) {
       double tmp_result[4];
       ErrorCode rval = MB_SUCCESS;
       for (int i = 0; i < num_tuples; i++) result[i] = 0.0;

diff --git a/src/LocalDiscretization/LinearTet.cpp b/src/LocalDiscretization/LinearTet.cpp
index 3eabe33..544cbd9 100644
--- a/src/LocalDiscretization/LinearTet.cpp
+++ b/src/LocalDiscretization/LinearTet.cpp
@@ -47,7 +47,7 @@ namespace moab
       return MB_SUCCESS;
     }
 
-    ErrorCode LinearTet::integrateFcn(const double *field, const double */*verts*/, const int nverts, const int num_tuples, const int /*ndim*/,
+    ErrorCode LinearTet::integrateFcn(const double *field, const double */*verts*/, const int nverts, const int /*ndim*/, const int num_tuples,
                                       double *work, double *result) 
     {
       assert(field && num_tuples > 0);

diff --git a/src/LocalDiscretization/QuadraticHex.cpp b/src/LocalDiscretization/QuadraticHex.cpp
index 0e6df67..e55930e 100644
--- a/src/LocalDiscretization/QuadraticHex.cpp
+++ b/src/LocalDiscretization/QuadraticHex.cpp
@@ -99,7 +99,7 @@ namespace moab
       return MB_SUCCESS;
     }
 
-    ErrorCode QuadraticHex::integrateFcn(const double */*field*/, const double */*verts*/, const int /*nverts*/, const int /*num_tuples*/, const int /*ndim*/,
+    ErrorCode QuadraticHex::integrateFcn(const double */*field*/, const double */*verts*/, const int /*nverts*/, const int /*ndim*/, const int /*num_tuples*/,
                                          double */*work*/, double */*result*/)
     {
       return MB_NOT_IMPLEMENTED;

diff --git a/src/LocalDiscretization/SpectralHex.cpp b/src/LocalDiscretization/SpectralHex.cpp
index 27194ad..dc636c9 100644
--- a/src/LocalDiscretization/SpectralHex.cpp
+++ b/src/LocalDiscretization/SpectralHex.cpp
@@ -8,14 +8,14 @@ namespace moab
 
   // filescope for static member data that is cached
 int SpectralHex::_n;
-double *SpectralHex::_z[3];
+real *SpectralHex::_z[3];
 lagrange_data SpectralHex::_ld[3];
 opt_data_3 SpectralHex::_data;
-double * SpectralHex::_odwork;
+real * SpectralHex::_odwork;
 
 bool SpectralHex::_init = false;
 
-void SpectralHex::Init(int order)
+    void SpectralHex::initFcn(const double *verts, const int nverts, double *&work)
 {
   if (_init && _n==order)
     return;

diff --git a/src/LocalDiscretization/SpectralQuad.cpp b/src/LocalDiscretization/SpectralQuad.cpp
index 121ba3e..681a5c7 100644
--- a/src/LocalDiscretization/SpectralQuad.cpp
+++ b/src/LocalDiscretization/SpectralQuad.cpp
@@ -6,11 +6,11 @@ namespace moab
     
   // filescope for static member data that is cached
 int SpectralQuad::_n;
-double *SpectralQuad::_z[2];
+real *SpectralQuad::_z[2];
 lagrange_data SpectralQuad::_ld[2];
 opt_data_2 SpectralQuad::_data;
-double * SpectralQuad::_odwork;
-double * SpectralQuad::_glpoints;
+real * SpectralQuad::_odwork;
+real * SpectralQuad::_glpoints;
 bool SpectralQuad::_init = false;
 
 SpectralQuad::SpectralQuad() : Map(0)
@@ -75,7 +75,8 @@ void SpectralQuad::set_gl_points( double * x, double * y, double *z)
   _xyz[1] = y;
   _xyz[2] = z;
 }
-CartVect SpectralQuad::evaluate( const CartVect& params ) const
+CartVect SpectralQuad::evalFcn(const double *params, const double *field, const int ndim, const int num_tuples, 
+                               double *work, double *result) 
 {
     //piece that we shouldn't want to cache
   int d=0;
@@ -93,7 +94,8 @@ CartVect SpectralQuad::evaluate( const CartVect& params ) const
   return result;
 }
   // replicate the functionality of hex_findpt
-bool SpectralQuad::evaluate_reverse(CartVect const & xyz, CartVect &params, double tol, const CartVect &init) const
+bool SpectralQuad::reverseEvalFcn(const double *posn, const double *verts, const int nverts, const int ndim,
+                                  const double tol, double *work, double *params, bool *is_inside)
 {
   params = init;
 
@@ -116,7 +118,8 @@ bool SpectralQuad::evaluate_reverse(CartVect const & xyz, CartVect &params, doub
 }
 
 
-Matrix3  SpectralQuad::jacobian(const CartVect& /*params*/) const
+Matrix3  SpectralQuad::jacobian(const double *params, const double *verts, const int nverts, const int ndim, 
+                                     double *work, double *result)
 {
     // not implemented
   Matrix3 J(0.);
@@ -137,7 +140,8 @@ void SpectralQuad::evaluate_vector(const CartVect& params, const double *field,
                     field,
                     _odwork);
 }
-void SpectralQuad:: integrate_vector(const double */*field_values*/, int /*num_tuples*/, double */*integral*/) const
+void SpectralQuad:: integrate_vector(const double *field, const double *verts, const int nverts, const int ndim,
+                                      const int num_tuples, double *work, double *result)
 {
     // not implemented
 }

diff --git a/src/LocalDiscretization/moab/ElemEvaluator.hpp b/src/LocalDiscretization/moab/ElemEvaluator.hpp
index f7a304a..161bfc5 100644
--- a/src/LocalDiscretization/moab/ElemEvaluator.hpp
+++ b/src/LocalDiscretization/moab/ElemEvaluator.hpp
@@ -9,6 +9,7 @@
 #include "moab/CN.hpp"
 
 namespace moab {
+
     typedef ErrorCode (*EvalFcn)(const double *params, const double *field, const int ndim, const int num_tuples, 
                           double *work, double *result);
 
@@ -48,7 +49,13 @@ namespace moab {
       EvalSet(EvalFcn eval, ReverseEvalFcn rev, JacobianFcn jacob, IntegrateFcn integ, InitFcn initf)
               : evalFcn(eval), reverseEvalFcn(rev), jacobianFcn(jacob), integrateFcn(integ), initFcn(initf)
           {}
-        
+
+        /** \brief Given an entity handle, get an appropriate eval set, based on type & #vertices */
+      static ErrorCode get_eval_set(Interface *mb, EntityHandle eh, EvalSet &eval_set);
+      
+        /** \brief Given type & #vertices, get an appropriate eval set */
+      static ErrorCode get_eval_set(EntityType tp, unsigned int num_vertices, EvalSet &eval_set);
+      
         /** \brief Operator= */
       EvalSet &operator=(const EvalSet &eval) {
         evalFcn = eval.evalFcn;
@@ -66,6 +73,18 @@ namespace moab {
       
     };
 
+        /** \brief Given an entity handle, get an appropriate eval set, based on type & #vertices */
+    inline ErrorCode EvalSet::get_eval_set(Interface *mb, EntityHandle eh, EvalSet &eval_set) 
+    {
+      int nv;
+      EntityType tp = mb->type_from_handle(eh);
+      const EntityHandle *connect;
+      ErrorCode rval = mb->get_connectivity(eh, connect, nv);
+      if (MB_SUCCESS != rval) return rval;
+      
+      return get_eval_set(tp, nv, eval_set);
+    }
+      
 /**\brief Class facilitating local discretization-related functions
  * \class ElemEvaluator
  * This class implements discretization-related functionality operating
@@ -86,55 +105,103 @@ namespace moab {
 
     class ElemEvaluator {
   public:
-        /** \brief Constructor */
+        /** \brief Constructor 
+         * \param impl MOAB instance
+         * \param ent Entity handle to cache on the evaluator
+         * \param tag Tag to cache on the evaluator
+         * \param tag_dim Tag dimension to cache on the evaluator
+         */
       ElemEvaluator(Interface *impl, EntityHandle ent = 0, Tag tag = 0, int tag_dim = -1);
 
-        /** \brief Evaluate cached tag at a given parametric location within the cached entity */
+        /** \brief Evaluate cached tag at a given parametric location within the cached entity 
+         * If evaluating coordinates, call set_tag(0, 0), which indicates coords instead of a tag.
+         * \param params Parameters at which to evaluate field
+         * \param result Result of evaluation
+         * \param num_tuples Size of evaluated field, in number of values
+         */
       ErrorCode eval(const double *params, double *result, int num_tuples = -1) const;
         
-        /** \brief Evaluate cached tag at a given parametric location within the cached entity */
-      ErrorCode eval(const CartVect &params, double *result, int num_tuples = -1) const;
-        
-        /** \brief Reverse-evaluate the cached entity at a given physical position */
+        /** \brief Reverse-evaluate the cached entity at a given physical position
+         * \param posn Position at which to evaluate parameters
+         * \param tol Tolerance of reverse evaluation, usually 10^-6 or so
+         * \param params Result of evaluation
+         * \param is_inside If non-NULL, returns true of resulting parameters place the point inside the element
+         *                  (in most cases, within [-1]*(dim)
+         */
       ErrorCode reverse_eval(const double *posn, double tol, double *params, bool *is_inside = NULL) const;
         
-        /** \brief Reverse-evaluate the cached entity at a given physical position */
-      ErrorCode reverse_eval(const CartVect &posn, double tol, CartVect &params, bool *is_inside = NULL) const;
-        
-        /** \brief Evaluate the jacobian of the cached entity at a given parametric location */
+        /** \brief Evaluate the jacobian of the cached entity at a given parametric location
+         * \param params Parameters at which to evaluate jacobian
+         * \param result Result of evaluation, in the form of a 3x3 matrix, stored in column-major order
+         */
       ErrorCode jacobian(const double *params, double *result) const;
         
-        /** \brief Evaluate the jacobian of the cached entity at a given parametric location */
-      ErrorCode jacobian(const CartVect &params, Matrix3 &result) const;
-        
-        /** \brief Integrate the cached tag over the cached entity */
+        /** \brief Integrate the cached tag over the cached entity
+         * \param result Result of the integration
+         */
       ErrorCode integrate(double *result) const;
       
-        /** \brief Return whether a physical position is inside the cached entity to within a tolerance */
+        /** \brief Return whether a physical position is inside the cached entity to within a tolerance
+         * \param params Parameters at which to query the element
+         * \param tol Tolerance, usually 10^-6 or so
+         */
       bool is_inside(const double *params, double tol) const;
 
-        /** \brief Return whether a physical position is inside the cached entity to within a tolerance */
-      bool is_inside(const CartVect &params, double tol) const;
-
-        /** \brief Set the eval set for a given type entity */
-      void set_eval_set(EntityType tp, const EvalSet &eval_set);
+        /** \brief Set the eval set for a given type entity
+         * \param tp Entity type for which to set the eval set
+         * \param eval_set Eval set object to use
+         */
+      ErrorCode set_eval_set(EntityType tp, const EvalSet &eval_set);
+      
+        /** \brief Set the eval set using a given entity handle
+        * This function queries the entity type and number of vertices on the entity to decide which type
+        * of shape function to use.
+        * NOTE: this function should only be called after setting a valid MOAB instance on the evaluator
+        * \param eh Entity handle whose type and #vertices are queried
+        */
+      ErrorCode set_eval_set(EntityHandle eh);
       
         /** \brief Get the eval set for a given type entity */
       inline EvalSet get_eval_set(EntityType tp) {return evalSets[tp];}
-      
-      inline EntityHandle get_ent_handle() const {return entHandle;};
+
+        /** \brief Set entity handle & cache connectivty & vertex positions */
       inline ErrorCode set_ent_handle(EntityHandle ent);
 
+        /** \brief Get entity handle for this ElemEval */
+      inline EntityHandle get_ent_handle() const {return entHandle;};
+
+        /* \brief Get the vertex handles cached here */
       inline const EntityHandle *get_vert_handles() const {return vertHandles;}
+
+        /* \brief Get the number of vertices for the cached entity */
       inline int get_num_verts() const {return numVerts;}
-      
+
+        /* \brief Get the tag handle cached on this entity */
       inline Tag get_tag_handle() const {return tagHandle;};
+
+        /* \brief Set the tag handle to cache on this evaluator
+         * To designate that vertex coordinates are the desired tag, pass in a tag handle of 0
+         * and a tag dimension of 0.
+         * \param tag Tag handle to cache, or 0 to cache vertex positions
+         * \param tag_dim Dimension of entities tagged with this tag
+         */
       inline ErrorCode set_tag_handle(Tag tag, int tag_dim = -1);
-      inline ErrorCode set_tag(const char *tag_name, int tag_dim = -1);
+
+        /* \brief Set the name of the tag to cache on this evaluator
+         * To designate that vertex coordinates are the desired tag, pass in "COORDS" as the name
+         * and a tag dimension of 0.
+         * \param tag Tag handle to cache, or 0 to cache vertex positions
+         * \param tag_dim Dimension of entities tagged with this tag
+         */
+      inline ErrorCode set_tag(const char *tag_name, int ent_dim = -1);
       
+        /* \brief Get the dimension of the entities on which tag is set */
       inline int get_tag_dim() const {return tagDim;};
+
+        /* \brief Set the dimension of entities having the tag */
       inline ErrorCode set_tag_dim(int dim);
 
+        /* \brief MOAB interface cached on this evaluator */
       inline Interface *get_moab() {return mbImpl;}
       
   private:
@@ -237,7 +304,7 @@ namespace moab {
         tagCoords = false;
       }
 
-      tagDim = (-1 == tag_dim ? entDim : tag_dim);
+      tagDim = (-1 == tag_dim ? 0 : tag_dim);
       
       if (entHandle) {
         if (0 == tagDim) {
@@ -256,6 +323,7 @@ namespace moab {
     inline ErrorCode ElemEvaluator::set_tag(const char *tag_name, int tag_dim) 
     {
       ErrorCode rval = MB_SUCCESS;
+      if (!tag_name || strlen(tag_name) == 0) return MB_FAILURE;
       Tag tag;
       if (!strcmp(tag_name, "COORDS")) {
         tagCoords = true;
@@ -297,13 +365,14 @@ namespace moab {
       return rval;
     }
 
-    inline void ElemEvaluator::set_eval_set(EntityType tp, const EvalSet &eval_set) 
+    inline ErrorCode ElemEvaluator::set_eval_set(EntityType tp, const EvalSet &eval_set) 
     {
       evalSets[tp] = eval_set;
       if (entHandle && evalSets[entType].initFcn) {
         ErrorCode rval = (*evalSets[entType].initFcn)(vertPos[0].array(), numVerts, workSpace);
-        if (MB_SUCCESS != rval) throw rval;
+        if (MB_SUCCESS != rval) return rval;
       }
+      return MB_SUCCESS;
     }
     
     inline ErrorCode ElemEvaluator::eval(const double *params, double *result, int num_tuples) const 
@@ -345,33 +414,13 @@ namespace moab {
                                                workSpace, result);
     }
 
-        /** \brief Evaluate cached tag at a given parametric location within the cached entity */
-    inline ErrorCode ElemEvaluator::eval(const CartVect &params, double *result, int num_tuples) const 
-    {
-      return eval(params.array(), result, num_tuples);
-    }
-        
-        /** \brief Reverse-evaluate the cached entity at a given physical position */
-    inline ErrorCode ElemEvaluator::reverse_eval(const CartVect &posn, double tol, CartVect &params, bool *is_in) const
-    {
-      return reverse_eval(posn.array(), tol, params.array(), is_in);
-    }
-        
-        /** \brief Evaluate the jacobian of the cached entity at a given parametric location */
-    inline ErrorCode ElemEvaluator::jacobian(const CartVect &params, Matrix3 &result) const
+    inline ErrorCode ElemEvaluator::set_eval_set(EntityHandle eh) 
     {
-      return jacobian(params.array(), result.array());
-    }
-        
-        /** \brief Return whether a physical position is inside the cached entity to within a tolerance */
-    inline bool ElemEvaluator::is_inside(const CartVect &params, double tol) const
-    {
-      return (params[0]+tol >= -1.0 && params[0]-tol <= 1.0 &&
-              params[1]+tol >= -1.0 && params[1]-tol <= 1.0 &&
-              params[2]+tol >= -1.0 && params[2]-tol <= 1.0);
+      EvalSet eset;
+      ErrorCode rval = EvalSet::get_eval_set(mbImpl, eh, evalSets[mbImpl->type_from_handle(eh)]); 
+      return rval;
     }
 
-      
 } // namespace moab
 
 #endif /*MOAB_ELEM_EVALUATOR_HPP*/

diff --git a/src/LocalDiscretization/moab/LinearHex.hpp b/src/LocalDiscretization/moab/LinearHex.hpp
index 79009cc..358899e 100644
--- a/src/LocalDiscretization/moab/LinearHex.hpp
+++ b/src/LocalDiscretization/moab/LinearHex.hpp
@@ -23,7 +23,7 @@ public:
                                double *work, double *result);
         
     /** \brief Forward-evaluation of field at parametric coordinates */
-  static ErrorCode integrateFcn(const double *field, const double *verts, const int nverts, const int num_tuples, const int ndim, 
+  static ErrorCode integrateFcn(const double *field, const double *verts, const int nverts, const int ndim, const int num_tuples, 
                                 double *work, double *result);
 
   static EvalSet eval_set() 
@@ -31,6 +31,15 @@ public:
         return EvalSet(evalFcn, reverseEvalFcn, jacobianFcn, integrateFcn, (InitFcn)NULL);
       }
       
+  static bool compatible(EntityType tp, int numv, EvalSet &eset) 
+      {
+        if (tp == MBHEX && numv == 8) {
+          eset = eval_set();
+          return true;
+        }
+        else return false;
+      }
+  
 protected:
     /* Preimages of the vertices -- "canonical vertices" -- are known as "corners". */
   static const double corner[8][3];

diff --git a/src/LocalDiscretization/moab/LinearQuad.hpp b/src/LocalDiscretization/moab/LinearQuad.hpp
index b83b8a6..b1c2ca8 100644
--- a/src/LocalDiscretization/moab/LinearQuad.hpp
+++ b/src/LocalDiscretization/moab/LinearQuad.hpp
@@ -23,14 +23,23 @@ public:
                                double *work, double *result);
         
     /** \brief Forward-evaluation of field at parametric coordinates */
-  static ErrorCode integrateFcn(const double *field, const double *verts, const int nverts, const int num_tuples, const int ndim, 
+  static ErrorCode integrateFcn(const double *field, const double *verts, const int nverts, const int ndim, const int num_tuples, 
                                 double *work, double *result);
 
   static EvalSet eval_set() 
       {
         return EvalSet(evalFcn, reverseEvalFcn, jacobianFcn, integrateFcn, NULL);
       }
-      
+
+  static bool compatible(EntityType tp, int numv, EvalSet &eset) 
+      {
+        if (tp == MBQUAD && numv == 4) {
+          eset = eval_set();
+          return true;
+        }
+        else return false;
+      }
+  
 protected:
     /* Preimages of the vertices -- "canonical vertices" -- are known as "corners". */
   static const double corner[4][2];

diff --git a/src/LocalDiscretization/moab/LinearTet.hpp b/src/LocalDiscretization/moab/LinearTet.hpp
index a3e50dc..c355c1b 100644
--- a/src/LocalDiscretization/moab/LinearTet.hpp
+++ b/src/LocalDiscretization/moab/LinearTet.hpp
@@ -23,7 +23,7 @@ public:
                                double *work, double *result);
         
     /** \brief Forward-evaluation of field at parametric coordinates */
-  static ErrorCode integrateFcn(const double *field, const double *verts, const int nverts, const int num_tuples, const int ndim,
+  static ErrorCode integrateFcn(const double *field, const double *verts, const int nverts, const int ndim, const int num_tuples, 
                                 double *work, double *result);
 
     /** \brief Initialize this EvalSet */
@@ -34,6 +34,15 @@ public:
         return EvalSet(evalFcn, reverseEvalFcn, jacobianFcn, integrateFcn, initFcn);
       }
       
+  static bool compatible(EntityType tp, int numv, EvalSet &eset) 
+      {
+        if (tp == MBTET && numv == 4) {
+          eset = eval_set();
+          return true;
+        }
+        else return false;
+      }
+  
 protected:
       
   static const double corner[4][3];

diff --git a/src/LocalDiscretization/moab/QuadraticHex.hpp b/src/LocalDiscretization/moab/QuadraticHex.hpp
index 51070e3..9fcbdd8 100644
--- a/src/LocalDiscretization/moab/QuadraticHex.hpp
+++ b/src/LocalDiscretization/moab/QuadraticHex.hpp
@@ -23,7 +23,7 @@ public:
                                double *work, double *result);
         
     /** \brief Forward-evaluation of field at parametric coordinates */
-  static ErrorCode integrateFcn(const double *field, const double *verts, const int nverts, const int num_tuples, const int ndim,
+  static ErrorCode integrateFcn(const double *field, const double *verts, const int nverts, const int ndim, const int num_tuples, 
                                 double *work, double *result);
 
   static EvalSet eval_set() 
@@ -31,6 +31,15 @@ public:
         return EvalSet(evalFcn, reverseEvalFcn, jacobianFcn, integrateFcn, NULL);
       }
       
+  static bool compatible(EntityType tp, int numv, EvalSet &eset) 
+      {
+        if (tp == MBHEX && numv == 27) {
+          eset = eval_set();
+          return true;
+        }
+        else return false;
+      }
+  
 protected:
   static double SH(const int i, const double params);
   static double DSH(const int i, const double params);

diff --git a/src/LocalDiscretization/moab/SpectralHex.hpp b/src/LocalDiscretization/moab/SpectralHex.hpp
index 50ce4e0..e9d7005 100644
--- a/src/LocalDiscretization/moab/SpectralHex.hpp
+++ b/src/LocalDiscretization/moab/SpectralHex.hpp
@@ -3,7 +3,8 @@
   /**\brief Shape function space for spectral hexahedron
    */
 
-#include "EvalSet.hpp"
+#include "ElemEvaluator.hpp"
+#include "SpectralFuncs.hpp"
 
 namespace moab 
 {
@@ -35,12 +36,22 @@ public:
         return EvalSet(evalFcn, reverseEvalFcn, jacobianFcn, integrateFcn, initFcn);
       }
       
+  static bool compatible(EntityType tp, int numv, EvalSet &eset) 
+      {
+        if (tp != MBHEX) return false;
+        int i;
+        for (i = 3; i*i*i == numv || i*i*i > numv; i++);
+        if (i*i*i != numv) return false;
+        eset = eval_set();
+        return true;
+      }
+  
 protected:
   static int _n;
-  static real *_z[3];
+  static double *_z[3];
   static lagrange_data _ld[3];
   static opt_data_3 _data;
-  static real * _odwork;// work area
+  static double * _odwork;// work area
   static bool init_;
 };// class SpectralHex
 

diff --git a/src/LocalDiscretization/moab/SpectralQuad.hpp b/src/LocalDiscretization/moab/SpectralQuad.hpp
index 2c956a7..b56e84c 100644
--- a/src/LocalDiscretization/moab/SpectralQuad.hpp
+++ b/src/LocalDiscretization/moab/SpectralQuad.hpp
@@ -3,7 +3,8 @@
   /*\brief Shape function space for spectral quad
    */
 
-#include "EvalSet.hpp"
+#include "ElemEvaluator.hpp"
+#include "SpectralFuncs.hpp"
 
 namespace moab 
 {
@@ -13,37 +14,47 @@ class SpectralQuad
 public:
     /** \brief Forward-evaluation of field at parametric coordinates */
   static ErrorCode evalFcn(const double *params, const double *field, const int ndim, const int num_tuples, 
-                           double *work, double *result) const;
+                           double *work, double *result);
         
     /** \brief Reverse-evaluation of parametric coordinates at physical space position */
   static ErrorCode reverseEvalFcn(const double *posn, const double *verts, const int nverts, const int ndim,
-                                  double *work, double *params) const;
+                                  const double tol, double *work, double *params, bool *is_inside);
         
     /** \brief Evaluate the jacobian at a specified parametric position */
   static ErrorCode jacobianFcn(const double *params, const double *verts, const int nverts, const int ndim, 
-                               double *work, double *result) const;
+                               double *work, double *result);
         
     /** \brief Forward-evaluation of field at parametric coordinates */
-  static ErrorCode integrateFcn(const double *field, const int num_tuples, double *work, double *result) const;
+  static ErrorCode integrateFcn(const double *field, const double *verts, const int nverts, const int ndim, const int num_tuples, double *work, double *result);
 
     /** \brief Initialize this EvalSet */
-  static ErrorCode initFcn(const EntityHandle ent, double *&work) const;
+  static ErrorCode initFcn(const double *verts, const int nverts, double *&work);
       
   static EvalSet eval_set() 
       {
         return EvalSet(evalFcn, reverseEvalFcn, jacobianFcn, integrateFcn, initFcn);
       }
       
+  static bool compatible(EntityType tp, int numv, EvalSet &eset) 
+      {
+        if (tp != MBQUAD) return false;
+        int i;
+        for (i = 3; i*i == numv || i*i > numv; i++);
+        if (i*i != numv) return false;
+        eset = eval_set();
+        return true;
+      }
+  
 protected:
   static int _n;
-  static real *_z[2];
+  static double *_z[2];
   static lagrange_data _ld[2];
   static opt_data_2 _data; // we should use only 2nd component
-  static real * _odwork;// work area
+  static double * _odwork;// work area
 
     // flag for initialization of data
   static bool _init;
-  static real * _glpoints; // it is a space we can use to store gl positions for elements
+  static double * _glpoints; // it is a space we can use to store gl positions for elements
     // on the fly; we do not have a tag yet for them, as in Nek5000 application
     // also, these positions might need to be moved on the sphere, for HOMME grids
     // do we project them or how do we move them on the sphere?

diff --git a/src/Makefile.am b/src/Makefile.am
index d7107d6..c50df45 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -53,7 +53,6 @@ libMOAB_la_SOURCES = \
   DenseTag.hpp \
   DenseTag.cpp \
   DualTool.cpp \
-  ElemUtil.cpp \
   ElementSequence.hpp \
   EntitySequence.cpp \
   EntitySequence.hpp \
@@ -162,7 +161,6 @@ nobase_libMOAB_la_include_HEADERS = \
   moab/HigherOrderFactory.hpp \
   moab/HomXform.hpp \
   moab/EigenDecomp.hpp \
-  moab/ElemUtil.hpp \
   moab/EntityType.hpp \
   moab/EntityHandle.hpp \
   moab/FBEngine.hpp \

diff --git a/src/Tree.cpp b/src/Tree.cpp
index c9edd95..b7cd7ee 100644
--- a/src/Tree.cpp
+++ b/src/Tree.cpp
@@ -54,7 +54,7 @@ namespace moab
       }
     }
 
-    ErrorCode Tree::compute_bounding_box(const Range& elems, CartVect &box_min, CartVect &box_max) const
+    ErrorCode Tree::compute_bounding_box(Interface &iface, const Range& elems, CartVect &box_min, CartVect &box_max)
     {
       ErrorCode rval;
       box_min = CartVect(HUGE_VAL);
@@ -68,7 +68,7 @@ namespace moab
         // vertices
       const Range::const_iterator elem_begin = elems.lower_bound( MBEDGE );
       for (i = elems.begin(); i != elem_begin; ++i) {
-        rval = moab()->get_coords( &*i, 1, coords.array() );
+        rval = iface.get_coords( &*i, 1, coords.array() );
         if (MB_SUCCESS != rval)
           return rval;
         box_accum( coords, box_min, box_max );
@@ -77,12 +77,12 @@ namespace moab
         // elements with vertex-handle connectivity list
       const Range::const_iterator poly_begin = elems.lower_bound( MBPOLYHEDRON, elem_begin );
       for (i = elem_begin; i != poly_begin; ++i) {
-        rval = moab()->get_connectivity( *i, conn, len, true );
+        rval = iface.get_connectivity( *i, conn, len, true );
         if (MB_SUCCESS != rval)
           return rval;
 
         for (int j = 0; j < len; ++j) {
-          rval = moab()->get_coords( conn+j, 1, coords.array() );
+          rval = iface.get_coords( conn+j, 1, coords.array() );
           if (MB_SUCCESS != rval)
             return rval;
           box_accum( coords, box_min, box_max );
@@ -92,14 +92,14 @@ namespace moab
         // polyhedra
       const Range::const_iterator set_begin  = elems.lower_bound( MBENTITYSET, poly_begin );
       for (i = poly_begin; i != set_begin; ++i) {
-        rval = moab()->get_connectivity( *i, conn, len, true );
+        rval = iface.get_connectivity( *i, conn, len, true );
         if (MB_SUCCESS != rval)
           return rval;
 
         for (int j = 0; j < len; ++j) {
-          rval = moab()->get_connectivity( conn[j], conn2, len2 );
+          rval = iface.get_connectivity( conn[j], conn2, len2 );
           for (int k = 0; k < len2; ++k) {
-            rval = moab()->get_coords( conn2+k, 1, coords.array() );
+            rval = iface.get_coords( conn2+k, 1, coords.array() );
             if (MB_SUCCESS != rval)
               return rval;
             box_accum( coords, box_min, box_max );
@@ -111,9 +111,9 @@ namespace moab
       CartVect tmin, tmax;
       for (i = set_begin; i != elems.end(); ++i) {
         Range tmp_elems;
-        rval = mbImpl->get_entities_by_handle(*i, tmp_elems);
+        rval = iface.get_entities_by_handle(*i, tmp_elems);
         if (MB_SUCCESS != rval) return rval;
-        rval = compute_bounding_box(tmp_elems, tmin, tmax);
+        rval = compute_bounding_box(iface, tmp_elems, tmin, tmax);
         if (MB_SUCCESS != rval) return rval;
       
         for (int j = 0; j < 3; ++j) {

diff --git a/src/moab/AdaptiveKDTree.hpp b/src/moab/AdaptiveKDTree.hpp
index 9fe87b0..d16a69d 100644
--- a/src/moab/AdaptiveKDTree.hpp
+++ b/src/moab/AdaptiveKDTree.hpp
@@ -220,13 +220,13 @@ namespace moab {
         //! methods for selecting candidate split planes
       enum CandidatePlaneSet {
             //! Candidiate planes at evenly spaced intervals 
-          SUBDIVISION,
+          SUBDIVISION=0,
             //! Like SUBDIVISION, except snap to closest vertex coordinate
-          SUBDIVISION_SNAP,
+          SUBDIVISION_SNAP, // = 1
             //! Median vertex coodinate values
-          VERTEX_MEDIAN,
+          VERTEX_MEDIAN, // = 2
             //! Random sampling of vertex coordinate values
-          VERTEX_SAMPLE
+          VERTEX_SAMPLE // = 3
       };
   
         //! Create tree root node

diff --git a/src/moab/Core.hpp b/src/moab/Core.hpp
index efa17e3..c633321 100644
--- a/src/moab/Core.hpp
+++ b/src/moab/Core.hpp
@@ -1134,6 +1134,8 @@ public:
   void print(const EntityHandle handle, const char *prefix,
              bool first_call = true) const;
 
+  ErrorCode print_entity_tags(std::string indent_prefix, const EntityHandle handle, TagType tp) const;
+  
   virtual ErrorCode get_last_error(std::string& info) const;
 
   virtual std::string get_error_string(const ErrorCode code) const;

diff --git a/src/moab/FindPtFuncs.h b/src/moab/FindPtFuncs.h
new file mode 100644
index 0000000..3419ad2
--- /dev/null
+++ b/src/moab/FindPtFuncs.h
@@ -0,0 +1,566 @@
+#ifndef FINDPTFUNCS_H
+#define FINDPTFUNCS_H
+
+#include "float.h"
+
+//======================================================
+// from types.h
+//======================================================
+
+/* integer type to use for everything */
+#if   defined(USE_LONG)
+#  define INTEGER long
+#elif defined(USE_LONG_LONG)
+#  define INTEGER long long
+#elif defined(USE_SHORT)
+#  define INTEGER short
+#else
+#  define INTEGER int
+#endif
+
+/* when defined, use the given type for global indices instead of INTEGER */
+#if   defined(USE_GLOBAL_LONG_LONG)
+#  define GLOBAL_INT long long
+#elif defined(USE_GLOBAL_LONG)
+#  define GLOBAL_INT long
+#else
+#  define GLOBAL_INT long
+#endif
+
+/* floating point type to use for everything */
+#if   defined(USE_FLOAT)
+   typedef float real;
+#  define floorr floorf
+#  define ceilr  ceilf
+#  define sqrtr  sqrtf
+#  define fabsr  fabsf
+#  define cosr   cosf
+#  define sinr   sinf
+#  define EPS   (128*FLT_EPSILON)
+#  define PI 3.1415926535897932384626433832795028841971693993751058209749445923F
+#elif defined(USE_LONG_DOUBLE)
+   typedef long double real;
+#  define floorr floorl
+#  define ceilr  ceill
+#  define sqrtr  sqrtl
+#  define fabsr  fabsl
+#  define cosr   cosl
+#  define sinr   sinl
+#  define EPS   (128*LDBL_EPSILON)
+#  define PI 3.1415926535897932384626433832795028841971693993751058209749445923L
+#else
+   typedef double real;
+#  define floorr floor
+#  define ceilr  ceil
+#  define sqrtr  sqrt
+#  define fabsr  fabs
+#  define cosr   cos
+#  define sinr   sin
+#  define EPS   (128*DBL_EPSILON)
+#  define PI 3.1415926535897932384626433832795028841971693993751058209749445923
+#endif
+
+/* apparently uint and ulong can be defined already in standard headers */
+#define uint uint_
+#define ulong ulong_
+#define sint sint_
+#define slong slong_
+
+typedef   signed INTEGER sint;
+typedef unsigned INTEGER uint;
+#undef INTEGER
+
+#ifdef GLOBAL_INT
+  typedef   signed GLOBAL_INT slong;
+  typedef unsigned GLOBAL_INT ulong;
+#else
+  typedef sint slong;
+  typedef uint ulong;
+#endif
+
+//======================================================
+// from poly.h
+//======================================================
+
+/* 
+  For brevity's sake, some names have been shortened
+  Quadrature rules
+    Gauss   -> Gauss-Legendre quadrature (open)
+    Lobatto -> Gauss-Lobatto-Legendre quadrature (closed at both ends)
+  Polynomial bases
+    Legendre -> Legendre basis
+    Gauss    -> Lagrangian basis using Gauss   quadrature nodes
+    Lobatto  -> Lagrangian basis using Lobatto quadrature nodes
+*/
+
+/*--------------------------------------------------------------------------
+   Legendre Polynomial Matrix Computation
+   (compute P_i(x_j) for i = 0, ..., n and a given set of x)
+  --------------------------------------------------------------------------*/
+
+/* precondition: n >= 1
+   inner index is x index (0 ... m-1);
+   outer index is Legendre polynomial number (0 ... n)
+ */
+void legendre_matrix(const real *x, int m, real *P, int n);
+
+/* precondition: n >= 1
+   inner index is Legendre polynomial number (0 ... n)
+   outer index is x index (0 ... m-1);
+ */
+void legendre_matrix_t(const real *x, int m, real *P, int n);
+
+/* precondition: n >= 1
+   compute P_i(x) with i = 0 ... n
+ */
+void legendre_row(real x, real *P, int n);
+
+
+/*--------------------------------------------------------------------------
+   Quadrature Nodes and Weights Calculation
+   
+   call the _nodes function before calling the _weights function
+  --------------------------------------------------------------------------*/
+
+void gauss_nodes(real *z, int n);   /* n nodes (order = 2n-1) */
+void lobatto_nodes(real *z, int n); /* n nodes (order = 2n-3) */
+
+void gauss_weights(const real *z, real *w, int n);
+void lobatto_weights(const real *z, real *w, int n);
+
+/*--------------------------------------------------------------------------
+   Lagrangian to Legendre Change-of-basis Matrix
+  --------------------------------------------------------------------------*/
+
+/* precondition: n >= 2
+   given the Gauss quadrature rule (z,w,n), compute the square matrix J
+   for transforming from the Gauss basis to the Legendre basis:
+   
+      u_legendre(i) = sum_j J(i,j) u_gauss(j)
+
+   computes J   = .5 (2i+1) w  P (z )
+             ij              j  i  j
+             
+   in column major format (inner index is i, the Legendre index)
+ */
+void gauss_to_legendre(const real *z, const real *w, int n, real *J);
+
+/* precondition: n >= 2
+   same as above, but
+   in row major format (inner index is j, the Gauss index)
+ */
+void gauss_to_legendre_t(const real *z, const real *w, int n, real *J);
+
+/* precondition: n >= 3
+   given the Lobatto quadrature rule (z,w,n), compute the square matrix J
+   for transforming from the Lobatto basis to the Legendre basis:
+   
+      u_legendre(i) = sum_j J(i,j) u_lobatto(j)
+
+   in column major format (inner index is i, the Legendre index)
+ */
+void lobatto_to_legendre(const real *z, const real *w, int n, real *J);
+
+/*--------------------------------------------------------------------------
+   Lagrangian basis function evaluation
+  --------------------------------------------------------------------------*/
+
+/* given the Lagrangian nodes (z,n) and evaluation points (x,m)
+   evaluate all Lagrangian basis functions at all points x
+   
+   inner index of output J is the basis function index (row-major format)
+   provide work array with space for 4*n doubles
+ */
+void lagrange_weights(const real *z, unsigned n,
+                      const real *x, unsigned m,
+                      real *J, real *work);
+
+/* given the Lagrangian nodes (z,n) and evaluation points (x,m)
+   evaluate all Lagrangian basis functions and their derivatives
+   
+   inner index of outputs J,D is the basis function index (row-major format)
+   provide work array with space for 6*n doubles
+ */
+void lagrange_weights_deriv(const real *z, unsigned n,
+                            const real *x, unsigned m,
+                            real *J, real *D, real *work);
+
+/*--------------------------------------------------------------------------
+   Speedy Lagrangian Interpolation
+   
+   Usage:
+   
+     lagrange_data p;
+     lagrange_setup(&p,z,n);    *  setup for nodes z[0 ... n-1] *
+     
+     the weights
+       p->J [0 ... n-1]     interpolation weights
+       p->D [0 ... n-1]     1st derivative weights
+       p->D2[0 ... n-1]     2nd derivative weights
+     are computed for a given x with:
+       lagrange_0(p,x);  *  compute p->J *
+       lagrange_1(p,x);  *  compute p->J, p->D *
+       lagrange_2(p,x);  *  compute p->J, p->D, p->D2 *
+       lagrange_2u(p);   *  compute p->D2 after call of lagrange_1(p,x); *
+     These functions use the z array supplied to setup
+       (that pointer should not be freed between calls)
+     Weights for x=z[0] and x=z[n-1] are computed during setup; access as:
+       p->J_z0, etc. and p->J_zn, etc.
+
+     lagrange_free(&p);  *  deallocate memory allocated by setup *
+  --------------------------------------------------------------------------*/
+
+typedef struct {
+  unsigned n;                /* number of Lagrange nodes            */
+  const real *z;             /* Lagrange nodes (user-supplied)      */
+  real *J, *D, *D2;          /* weights for 0th,1st,2nd derivatives */
+  real *J_z0, *D_z0, *D2_z0; /* ditto at z[0]   (computed at setup) */
+  real *J_zn, *D_zn, *D2_zn; /* ditto at z[n-1] (computed at setup) */
+  real *w, *d, *u0, *v0, *u1, *v1, *u2, *v2; /* work data           */
+} lagrange_data;
+
+void lagrange_setup(lagrange_data *p, const real *z, unsigned n);
+void lagrange_free(lagrange_data *p);
+
+void lagrange_0(lagrange_data *p, real x) ;
+void lagrange_1(lagrange_data *p, real x) ;
+void lagrange_2(lagrange_data *p, real x) ;
+void lagrange_2u(lagrange_data *p) ;
+
+//======================================================
+// from tensor.h
+//======================================================
+
+/*--------------------------------------------------------------------------
+   1-,2-,3-d Tensor Application
+   
+   the 3d case:
+   tensor_f3(R,mr,nr, S,ms,ns, T,mt,nt, u,v, work1,work2)
+     gives v = [ R (x) S (x) T ] u
+     where R is mr x nr, S is ms x ns, T is mt x nt,
+       each in row- or column-major format according to f := r | c
+     u is nr x ns x nt in column-major format (inner index is r)
+     v is mr x ms x mt in column-major format (inner index is r)
+  --------------------------------------------------------------------------*/
+
+void tensor_c1(const real *R, unsigned mr, unsigned nr, 
+               const real *u, real *v);
+void tensor_r1(const real *R, unsigned mr, unsigned nr, 
+               const real *u, real *v);
+
+/* work holds mr*ns reals */
+void tensor_c2(const real *R, unsigned mr, unsigned nr,
+               const real *S, unsigned ms, unsigned ns,
+               const real *u, real *v, real *work);
+void tensor_r2(const real *R, unsigned mr, unsigned nr,
+               const real *S, unsigned ms, unsigned ns,
+               const real *u, real *v, real *work);
+
+/* work1 holds mr*ns*nt reals,
+   work2 holds mr*ms*nt reals */
+void tensor_c3(const real *R, unsigned mr, unsigned nr,
+               const real *S, unsigned ms, unsigned ns,
+               const real *T, unsigned mt, unsigned nt,
+               const real *u, real *v, real *work1, real *work2);
+void tensor_r3(const real *R, unsigned mr, unsigned nr,
+               const real *S, unsigned ms, unsigned ns,
+               const real *T, unsigned mt, unsigned nt,
+               const real *u, real *v, real *work1, real *work2);
+
+/*--------------------------------------------------------------------------
+   1-,2-,3-d Tensor Application of Row Vectors (for Interpolation)
+   
+   the 3d case:
+   v = tensor_i3(Jr,nr, Js,ns, Jt,nt, u, work)
+   same effect as tensor_r3(Jr,1,nr, Js,1,ns, Jt,1,nt, u,&v, work1,work2):
+     gives v = [ Jr (x) Js (x) Jt ] u
+     where Jr, Js, Jt are row vectors (interpolation weights)
+     u is nr x ns x nt in column-major format (inner index is r)
+     v is a scalar
+  --------------------------------------------------------------------------*/
+
+real tensor_i1(const real *Jr, unsigned nr, const real *u);
+
+/* work holds ns reals */
+real tensor_i2(const real *Jr, unsigned nr,
+               const real *Js, unsigned ns,
+               const real *u, real *work);
+
+/* work holds ns*nt + nt reals */
+real tensor_i3(const real *Jr, unsigned nr,
+               const real *Js, unsigned ns,
+               const real *Jt, unsigned nt,
+               const real *u, real *work);
+
+/*--------------------------------------------------------------------------
+   1-,2-,3-d Tensor Application of Row Vectors
+             for simultaneous Interpolation and Gradient computation
+   
+   the 3d case:
+   v = tensor_ig3(Jr,Dr,nr, Js,Ds,ns, Jt,Dt,nt, u,g, work)
+     gives v   = [ Jr (x) Js (x) Jt ] u
+           g_0 = [ Dr (x) Js (x) Jt ] u
+           g_1 = [ Jr (x) Ds (x) Jt ] u
+           g_2 = [ Jr (x) Js (x) Dt ] u
+     where Jr,Dr,Js,Ds,Jt,Dt are row vectors
+       (interpolation & derivative weights)
+     u is nr x ns x nt in column-major format (inner index is r)
+     v is a scalar, g is an array of 3 reals
+  --------------------------------------------------------------------------*/
+
+real tensor_ig1(const real *Jr, const real *Dr, unsigned nr,
+                const real *u, real *g);
+
+/* work holds 2*ns reals */
+real tensor_ig2(const real *Jr, const real *Dr, unsigned nr,
+                const real *Js, const real *Ds, unsigned ns,
+                const real *u, real *g, real *work);
+
+/* work holds 2*ns*nt + 3*ns reals */
+real tensor_ig3(const real *Jr, const real *Dr, unsigned nr,
+                const real *Js, const real *Ds, unsigned ns,
+                const real *Jt, const real *Dt, unsigned nt,
+                const real *u, real *g, real *work);
+
+//======================================================
+// from findpt.h
+//======================================================
+
+typedef struct {
+  const real *xw[2];   /* geometry data */
+  real *z[2];          /* lobatto nodes */
+  lagrange_data ld[2]; /* interpolation, derivative weights & data */
+  unsigned nptel;      /* nodes per element */
+  struct findpt_hash_data_2 *hash;   /* geometric hashing data */
+  struct findpt_listel *list, **sorted, **end;
+                                        /* pre-allocated list of elements to
+                                           check (found by hashing), and
+                                           pre-allocated list of pointers into
+                                           the first list for sorting */
+  struct findpt_opt_data_2 *od; /* data for the optimization algorithm */
+  real *od_work;
+} findpt_data_2;
+
+typedef struct {
+  const real *xw[3];   /* geometry data */
+  real *z[3];          /* lobatto nodes */
+  lagrange_data ld[3]; /* interpolation, derivative weights & data */
+  unsigned nptel;      /* nodes per element */
+  struct findpt_hash_data_3 *hash;   /* geometric hashing data */
+  struct findpt_listel *list, **sorted, **end;
+                                        /* pre-allocated list of elements to
+                                           check (found by hashing), and
+                                           pre-allocated list of pointers into
+                                           the first list for sorting */
+  struct findpt_opt_data_3 *od; /* data for the optimization algorithm */
+  real *od_work;
+} findpt_data_3;
+
+findpt_data_2 *findpt_setup_2(
+          const real *const xw[2], const unsigned n[2], uint nel,
+          uint max_hash_size, real bbox_tol);
+findpt_data_3 *findpt_setup_3(
+          const real *const xw[3], const unsigned n[3], uint nel,
+          uint max_hash_size, real bbox_tol);
+
+void findpt_free_2(findpt_data_2 *p);
+void findpt_free_3(findpt_data_3 *p);
+
+const real *findpt_allbnd_2(const findpt_data_2 *p);
+const real *findpt_allbnd_3(const findpt_data_3 *p);
+
+typedef int (*findpt_func)(void *, const real *, int, uint *, real *, real *);
+int findpt_2(findpt_data_2 *p, const real x[2], int guess,
+             uint *el, real r[2], real *dist);
+int findpt_3(findpt_data_3 *p, const real x[3], int guess,
+             uint *el, real r[3], real *dist);
+
+inline void findpt_weights_2(findpt_data_2 *p, const real r[2])
+{
+  lagrange_0(&p->ld[0],r[0]);
+  lagrange_0(&p->ld[1],r[1]);
+}
+
+inline void findpt_weights_3(findpt_data_3 *p, const real r[3])
+{
+  lagrange_0(&p->ld[0],r[0]);
+  lagrange_0(&p->ld[1],r[1]);
+  lagrange_0(&p->ld[2],r[2]);
+}
+
+inline double findpt_eval_2(findpt_data_2 *p, const real *u)
+{
+  return tensor_i2(p->ld[0].J,p->ld[0].n,
+                   p->ld[1].J,p->ld[1].n,
+                   u, p->od_work);
+}
+
+inline double findpt_eval_3(findpt_data_3 *p, const real *u)
+{
+  return tensor_i3(p->ld[0].J,p->ld[0].n,
+                   p->ld[1].J,p->ld[1].n,
+                   p->ld[2].J,p->ld[2].n,
+                   u, p->od_work);
+}
+
+//======================================================
+// from extrafindpt.h
+//======================================================
+
+typedef struct {
+  unsigned constraints;
+  unsigned dn, d1, d2;
+  real *x[3], *fdn[3];
+} opt_face_data_3;
+
+typedef struct {
+  unsigned constraints;
+  unsigned de, d1, d2;
+  real *x[3], *fd1[3], *fd2[3];
+} opt_edge_data_3;
+
+typedef struct {
+  unsigned constraints;
+  real x[3], jac[9];
+} opt_point_data_3;
+
+typedef struct {
+  lagrange_data *ld;
+  unsigned size[4];
+  const real *elx[3];
+  opt_face_data_3 fd;
+  opt_edge_data_3 ed;
+  opt_point_data_3 pd;
+  real *work;
+  real x[3], jac[9];
+} opt_data_3;
+
+
+void opt_alloc_3(opt_data_3 *p, lagrange_data *ld);
+void opt_free_3(opt_data_3 *p);
+double opt_findpt_3(opt_data_3 *p, const real *const elx[3],
+                           const real xstar[3], real r[3], unsigned *constr);
+void opt_vol_set_intp_3(opt_data_3 *p, const real r[3]);
+
+const unsigned opt_no_constraints_2 = 3+1;
+const unsigned opt_no_constraints_3 = 9+3+1;
+
+/* for 2d spectralQuad */
+/*--------------------------------------------------------------------------
+
+   2 - D
+
+  --------------------------------------------------------------------------*/
+
+typedef struct {
+  unsigned constraints;
+  unsigned de, d1;
+  real *x[2], *fd1[2];
+} opt_edge_data_2;
+
+typedef struct {
+  unsigned constraints;
+  real x[2], jac[4];
+} opt_point_data_2;
+
+typedef struct {
+  lagrange_data *ld;
+  unsigned size[3];
+  const real *elx[2];
+  opt_edge_data_2 ed;
+  opt_point_data_2 pd;
+  real *work;
+  real x[2], jac[4];
+} opt_data_2;
+void opt_alloc_2(opt_data_2 *p, lagrange_data *ld);
+void opt_free_2(opt_data_2 *p);
+double opt_findpt_2(opt_data_2 *p, const real *const elx[2],
+                           const real xstar[2], real r[2], unsigned *constr);
+
+//======================================================
+// from errmem.h
+//======================================================
+
+/* requires:
+     <stdlib.h> for malloc, calloc, realloc, free
+*/
+
+/*--------------------------------------------------------------------------
+   Error Reporting
+   Memory Allocation Wrappers to Catch Out-of-memory
+  --------------------------------------------------------------------------*/
+
+/* #include "malloc.h" */
+#include <stdlib.h>
+
+#ifdef __GNUC__
+void fail(const char *fmt, ...) __attribute__ ((noreturn));
+#define MAYBE_UNUSED __attribute__ ((unused))
+#else
+void fail(const char *fmt, ...);
+#define MAYBE_UNUSED
+#endif
+
+#if 0
+{}
+#endif
+
+static void *smalloc(size_t size, const char *file) MAYBE_UNUSED;
+static void *smalloc(size_t size, const char *file)
+{
+  void *res = malloc(size);
+  if(!res && size) fail("%s: allocation of %d bytes failed\n",file,(int)size);
+  return res;
+}
+
+static void *scalloc(size_t nmemb, size_t size, const char *file) MAYBE_UNUSED;
+static void *scalloc(size_t nmemb, size_t size, const char *file)
+{
+  void *res = calloc(nmemb, size);
+  if(!res && nmemb)
+    fail("%s: allocation of %d bytes failed\n",file,(int)size*nmemb);
+  return res;
+}
+
+static void *srealloc(void *ptr, size_t size, const char *file) MAYBE_UNUSED;
+static void *srealloc(void *ptr, size_t size, const char *file)
+{
+  void *res = realloc(ptr, size);
+  if(!res && size) fail("%s: allocation of %d bytes failed\n",file,(int)size);
+  return res;
+}
+
+#define tmalloc(type, count) \
+  ((type*) smalloc((count)*sizeof(type),__FILE__) )
+#define tcalloc(type, count) \
+  ((type*) scalloc((count),sizeof(type),__FILE__) )
+#define trealloc(type, ptr, count) \
+  ((type*) srealloc((ptr),(count)*sizeof(type),__FILE__) )
+/*
+typedef struct { size_t size; void *ptr; } buffer;
+
+static void buffer_init_(buffer *b, size_t size, const char *file) MAYBE_UNUSED;
+static void buffer_init_(buffer *b, size_t size, const char *file)
+{
+  b->size=size, b->ptr=smalloc(size,file);
+}
+static void buffer_reserve_(buffer *b, size_t min, const char *file)
+  MAYBE_UNUSED;
+static void buffer_reserve_(buffer *b, size_t min, const char *file)
+{
+  size_t size = b->size;
+  if(size<min) {
+    size+=size/2+1;
+    if(size<min) size=min;
+    b->ptr=srealloc(b->ptr,size,file);
+  }
+}
+static void buffer_free(buffer *b) MAYBE_UNUSED;
+static void buffer_free(buffer *b) { free(b->ptr); }
+
+#define buffer_init(b,size) buffer_init_(b,size,__FILE__)
+#define buffer_reserve(b,min) buffer_reserve_(b,min,__FILE__)
+*/
+#endif
+
+

diff --git a/src/moab/Tree.hpp b/src/moab/Tree.hpp
index b30326f..7a6a9d2 100644
--- a/src/moab/Tree.hpp
+++ b/src/moab/Tree.hpp
@@ -140,40 +140,44 @@ namespace moab {
                                         EntityHandle *start_node = NULL) = 0;
 
         /** \brief Compute bounding box of entities in elems
+         * \param iface MOAB interface handle
          * \param elems Entities for which bounding box is computed
          * \param box_min Minimum corner of box
          * \param box_max Maximum corner of box
          * \return This function returns error only under catastrophic; in the case of no entities, 
          *          it just returns a zero-extent box.
          */
-      ErrorCode compute_bounding_box(const Range& elems, CartVect &box_min, CartVect &box_max) const;
+      static ErrorCode compute_bounding_box(Interface &iface, const Range& elems, CartVect &box_min, CartVect &box_max);
       
         /** \brief Compute bounding box of entities in elems
+         * \param iface MOAB interface handle
          * \param elems Entities for which bounding box is computed
          * \param box_min Minimum corner of box
          * \param box_max Maximum corner of box
          * \return This function returns error only under catastrophic; in the case of no entities, 
          *          it just returns a zero-extent box.
          */
-      ErrorCode compute_bounding_box(const Range& elems, double box_min[3], double box_max[3]) const;
+      static ErrorCode compute_bounding_box(Interface &iface, const Range& elems, double box_min[3], double box_max[3]);
       
         /** \brief Compute bounding box of an entity
+         * \param iface MOAB interface handle
          * \param ent Entity for which bounding box is computed
          * \param box_min Minimum corner of box
          * \param box_max Maximum corner of box
          * \return This function returns error only under catastrophic; in the case of no entities, 
          *          it just returns a zero-extent box.
          */
-      ErrorCode compute_bounding_box(const EntityHandle ent, CartVect &box_min, CartVect &box_max) const;
+      static ErrorCode compute_bounding_box(Interface &iface, const EntityHandle ent, CartVect &box_min, CartVect &box_max);
       
         /** \brief Compute bounding box of an entity
+         * \param iface MOAB interface handle
          * \param ent Entity for which bounding box is computed
          * \param box_min Minimum corner of box
          * \param box_max Maximum corner of box
          * \return This function returns error only under catastrophic; in the case of no entities, 
          *          it just returns a zero-extent box.
          */
-      ErrorCode compute_bounding_box(const EntityHandle ent, double box_min[3], double box_max[3]) const;
+      static ErrorCode compute_bounding_box(Interface &iface, const EntityHandle ent, double box_min[3], double box_max[3]);
       
         /** \brief Return the MOAB interface associated with this tree
          */
@@ -275,21 +279,21 @@ namespace moab {
       return MB_SUCCESS;
     }
   
-    inline ErrorCode Tree::compute_bounding_box(const Range &elems, double box_min[3], double box_max[3]) const
+    inline ErrorCode Tree::compute_bounding_box(Interface &iface, const Range &elems, double box_min[3], double box_max[3]) 
     {
-      return compute_bounding_box(elems, *reinterpret_cast<CartVect*>(box_min), *reinterpret_cast<CartVect*>(box_max));
+      return compute_bounding_box(iface, elems, *reinterpret_cast<CartVect*>(box_min), *reinterpret_cast<CartVect*>(box_max));
     }
   
-    inline ErrorCode Tree::compute_bounding_box(const EntityHandle ent, double box_min[3], double box_max[3]) const
+    inline ErrorCode Tree::compute_bounding_box(Interface &iface, const EntityHandle ent, double box_min[3], double box_max[3]) 
     {
       Range tmp_range(ent, ent);
-      return compute_bounding_box(tmp_range, *reinterpret_cast<CartVect*>(box_min), *reinterpret_cast<CartVect*>(box_max));
+      return compute_bounding_box(iface, tmp_range, *reinterpret_cast<CartVect*>(box_min), *reinterpret_cast<CartVect*>(box_max));
     }
   
-    inline ErrorCode Tree::compute_bounding_box(const EntityHandle ent, CartVect &box_min, CartVect &box_max) const
+    inline ErrorCode Tree::compute_bounding_box(Interface &iface, const EntityHandle ent, CartVect &box_min, CartVect &box_max) 
     {
       Range tmp_range(ent, ent);
-      return compute_bounding_box(tmp_range, box_min, box_max);
+      return compute_bounding_box(iface, tmp_range, box_min, box_max);
     }
   
     inline ErrorCode Tree::get_info(EntityHandle /* root */,

diff --git a/src/parallel/ParallelMergeMesh.cpp b/src/parallel/ParallelMergeMesh.cpp
index e6e1cd1..3d37bf0 100644
--- a/src/parallel/ParallelMergeMesh.cpp
+++ b/src/parallel/ParallelMergeMesh.cpp
@@ -154,7 +154,7 @@ namespace moab{
     double box[6];
     if(mySkinEnts[0].size() != 0){
       AdaptiveKDTree kd(myMB);
-      rval = kd.bounding_box(mySkinEnts[0],box, box+3);
+      rval = kd.compute_bounding_box(*myMB, mySkinEnts[0], box, box+3);
       if(rval != MB_SUCCESS){
 	return rval;
       }

diff --git a/test/elem_eval_test.cpp b/test/elem_eval_test.cpp
index 75ed95e..f2a4d96 100644
--- a/test/elem_eval_test.cpp
+++ b/test/elem_eval_test.cpp
@@ -53,12 +53,12 @@ void test_eval(ElemEvaluator &ee, bool test_integrate)
       for (params[2] = -1; params[2] <= 1; params[2] += 0.2) {
 
           // forward/reverse evaluation should get back to the same point, within tol
-        rval = ee.eval(params, posn.array()); CHECK_ERR(rval);
-        rval = ee.reverse_eval(posn, EPS1, params2, &is_inside); CHECK_ERR(rval);
+        rval = ee.eval(params.array(), posn.array()); CHECK_ERR(rval);
+        rval = ee.reverse_eval(posn.array(), EPS1, params2.array(), &is_inside); CHECK_ERR(rval);
         CHECK_REAL_EQUAL(0.0, (params - params2).length(), EPS1);
 
           // jacobian should be >= 0
-        rval = ee.jacobian(params, jacob); CHECK_ERR(rval);
+        rval = ee.jacobian(params.array(), jacob.array()); CHECK_ERR(rval);
         CHECK(jacob.determinant() >= 0.0);
         
       }

diff --git a/test/perf/Makefile.am b/test/perf/Makefile.am
index f98d653..07b90a0 100644
--- a/test/perf/Makefile.am
+++ b/test/perf/Makefile.am
@@ -7,12 +7,11 @@ AM_CPPFLAGS += -I$(top_srcdir)/src \
 LDADD = $(top_builddir)/src/libMOAB.la
 
 check_PROGRAMS = perf seqperf adj_time perftool
-noinst_PROGRAMS = point_in_elem 
+noinst_PROGRAMS = 
 
 perf_SOURCES = perf.cpp
 seqperf_SOURCES = seqperf.cpp
 adj_time_SOURCES = adj_time.cpp
-point_in_elem_SOURCES = point_in_elem.cpp
 perftool_SOURCES = perftool.cpp
 
 if ENABLE_imesh

diff --git a/test/perf/point_location/Makefile.am b/test/perf/point_location/Makefile.am
index d291d97..3590d6a 100644
--- a/test/perf/point_location/Makefile.am
+++ b/test/perf/point_location/Makefile.am
@@ -2,7 +2,10 @@
 AM_CPPFLAGS += -I$(top_srcdir)/src \
                -I$(top_srcdir)/src/io/mhdf/include \
                -I$(top_builddir)/ \
+               -I$(top_builddir)/include \
                -I$(top_srcdir)/src/LocalDiscretization/ \
+               -I$(top_srcdir)/tools/mbcoupler \
+               -I$(top_srcdir)/src/moab/point_locator/lotte \
                -DIS_BUILDING_MB
             
 LDADD = $(top_builddir)/src/libMOAB.la

diff --git a/test/perf/point_location/elem_eval_time.cpp b/test/perf/point_location/elem_eval_time.cpp
index 995c5ff..2507616 100644
--- a/test/perf/point_location/elem_eval_time.cpp
+++ b/test/perf/point_location/elem_eval_time.cpp
@@ -3,6 +3,7 @@
 #include "moab/ProgOptions.hpp"
 #include "moab/CartVect.hpp"
 #include "moab/ElemEvaluator.hpp"
+#include "ElemUtil.hpp"
 #include <iostream>
 #include <time.h>
 #include <stdlib.h>
@@ -66,7 +67,7 @@ void parse_options(ProgOptions &opts, int &dim, std::string &filename)
   opts.addOpt<std::string>(std::string("filename,f"), std::string("Filename containing mesh"), &filename);
 }
 
-ErrorCode time_forward_eval(ElemEvaluator &eeval, Range &elems, 
+ErrorCode time_forward_eval(Interface &mbi, int method, Range &elems, 
                             std::vector<CartVect> &params, std::vector<CartVect> &coords, 
                             double &evtime) 
 {
@@ -74,18 +75,39 @@ ErrorCode time_forward_eval(ElemEvaluator &eeval, Range &elems,
   ErrorCode rval;
   Range::iterator rit;
   unsigned int i;
-  for (rit = elems.begin(), i = 0; rit != elems.end(); rit++, i++) {
-    eeval.set_ent_handle(*rit);
-    rval = eeval.eval(params[i].array(), coords[i].array(), 3);
+  if (ELEMEVAL == method) {
+      // construct ElemEvaluator
+    EvalSet eset;
+    ElemEvaluator eeval(&mbi);
+    eeval.set_eval_set(*elems.begin());
+    eeval.set_tag_handle(0, 0); // indicates coordinates as the field to evaluate
+  
+    for (rit = elems.begin(), i = 0; rit != elems.end(); rit++, i++) {
+      eeval.set_ent_handle(*rit);
+      rval = eeval.eval(params[i].array(), coords[i].array(), 3);
 #ifndef NDEBUG
-    if (MB_SUCCESS != rval) return rval;
+      if (MB_SUCCESS != rval) return rval;
 #endif
+    }
+  }
+  else if (ELEMUTIL == method) {
+    std::vector<CartVect> vcoords(MAX_NODES_PER_ELEMENT);
+    const EntityHandle *connect;
+    int nconn;
+    Element::Map *elemmap = NULL;
+    for (rit = elems.begin(), i = 0; rit != elems.end(); rit++, i++) {
+      rval = mbi.get_connectivity(*rit, connect, nconn); CHK(rval, "get_connectivity");
+      rval = mbi.get_coords(connect, nconn, vcoords[0].array()); CHK(rval, "get_coords");
+      rval = get_elem_map(mbi.type_from_handle(*rit), vcoords, nconn, elemmap); CHK(rval, "get_elem_map");
+      coords[i] = elemmap->evaluate(params[i]);
+    }
   }
+  
   evtime = mytime() - evtime;
   return MB_SUCCESS;
 }
 
-ErrorCode time_reverse_eval(ElemEvaluator &eeval, Range &elems, 
+ErrorCode time_reverse_eval(Interface *mbi, int method, Range &elems, 
                             std::vector<CartVect> &coords, std::vector<CartVect> &params, 
                             double &retime) 
 {
@@ -93,20 +115,38 @@ ErrorCode time_reverse_eval(ElemEvaluator &eeval, Range &elems,
   ErrorCode rval;
   Range::iterator rit;
   unsigned int i;
-  bool ins;
-  for (rit = elems.begin(), i = 0; rit != elems.end(); rit++, i++) {
-    eeval.set_ent_handle(*rit);
-    rval = eeval.reverse_eval(coords[i].array(), 1.0e-6, params[i].array(), &ins);
-    assert(ins);
+  if (ELEMEVAL == method) {
+    EvalSet eset;
+    ElemEvaluator eeval(&mbi);
+    eeval.set_eval_set(*elems.begin());
+    eeval.set_tag_handle(0, 0); // indicates coordinates as the field to evaluate    
+    bool ins;
+    for (rit = elems.begin(), i = 0; rit != elems.end(); rit++, i++) {
+      eeval.set_ent_handle(*rit);
+      rval = eeval.reverse_eval(coords[i].array(), 1.0e-6, params[i].array(), &ins);
+      assert(ins);
 #ifndef NDEBUG
-    if (MB_SUCCESS != rval) return rval;
+      if (MB_SUCCESS != rval) return rval;
 #endif
+    }
+  }
+  else if (ELEMUTIL == method) {
+    std::vector<CartVect> vcoords(MAX_NODES_PER_ELEMENT);
+    const EntityHandle *connect;
+    int nconn;
+    Element::Map *elemmap = NULL;
+    for (rit = elems.begin(), i = 0; rit != elems.end(); rit++, i++) {
+      rval = mbi.get_connectivity(*rit, connect, nconn); CHK(rval, "get_connectivity");
+      rval = mbi.get_coords(connect, nconn, vcoords[0].array()); CHK(rval, "get_coords");
+      rval = get_elem_map(mbi.type_from_handle(*rit), vcoords, nconn, elemmap); CHK(rval, "get_elem_map");
+      coords[i] = elemmap->ievaluate(coords[i].array, 1.0e-6);
+    }
   }
   retime = mytime() - retime;
   return MB_SUCCESS;
 }
 
-ErrorCode time_jacobian(ElemEvaluator &eeval, Range &elems, std::vector<CartVect> &params, 
+ErrorCode time_jacobian(Interface *mbi, int method, Range &elems, std::vector<CartVect> &params, 
                         double &jactime) 
 {
   jactime = mytime();
@@ -114,29 +154,67 @@ ErrorCode time_jacobian(ElemEvaluator &eeval, Range &elems, std::vector<CartVect
   Range::iterator rit;
   unsigned int i;
   Matrix3 jac;
-  for (rit = elems.begin(), i = 0; rit != elems.end(); rit++, i++) {
-    eeval.set_ent_handle(*rit);
-    rval = eeval.jacobian(params[i].array(), jac.array());
+  if (ELEMEVAL == method) {
+    EvalSet eset;
+    ElemEvaluator eeval(&mbi);
+    eeval.set_eval_set(*elems.begin());
+    eeval.set_tag_handle(0, 0); // indicates coordinates as the field to evaluate    
+    for (rit = elems.begin(), i = 0; rit != elems.end(); rit++, i++) {
+      eeval.set_ent_handle(*rit);
+      rval = eeval.jacobian(params[i].array(), jac.array());
 #ifndef NDEBUG
-    if (MB_SUCCESS != rval) return rval;
+      if (MB_SUCCESS != rval) return rval;
 #endif
+    }
+  }
+  else if (ELEMUTIL == method) {
+    std::vector<CartVect> vcoords(MAX_NODES_PER_ELEMENT);
+    const EntityHandle *connect;
+    int nconn;
+    Element::Map *elemmap = NULL;
+    for (rit = elems.begin(), i = 0; rit != elems.end(); rit++, i++) {
+      rval = mbi.get_connectivity(*rit, connect, nconn); CHK(rval, "get_connectivity");
+      rval = mbi.get_coords(connect, nconn, vcoords[0].array()); CHK(rval, "get_coords");
+      rval = get_elem_map(mbi.type_from_handle(*rit), vcoords, nconn, elemmap); CHK(rval, "get_elem_map");
+      jac = elemmap->jacobian(params[i].array());
+    }
   }
   jactime = mytime() - jactime;
   return MB_SUCCESS;
 }
 
-ErrorCode time_integrate(ElemEvaluator &eeval, Tag tag, Range &elems, double &inttime) 
+ErrorCode time_integrate(Interface *mbi, int method, Tag tag, Range &elems, double &inttime) 
 {
   inttime = mytime();
   ErrorCode rval;
   double integral;
-  rval = eeval.set_tag_handle(tag, 0); CHK(rval, "set_tag_handle");
-  for (Range::iterator rit = elems.begin(); rit != elems.end(); rit++) {
-    eeval.set_ent_handle(*rit);
-    rval = eeval.integrate(&integral);
+  if (ELEMEVAL == method) {
+    EvalSet eset;
+    ElemEvaluator eeval(&mbi);
+    eeval.set_eval_set(*elems.begin());
+    eeval.set_tag_handle(0, 0); // indicates coordinates as the field to evaluate    
+    rval = eeval.set_tag_handle(tag, 0); CHK(rval, "set_tag_handle");
+    for (Range::iterator rit = elems.begin(); rit != elems.end(); rit++) {
+      eeval.set_ent_handle(*rit);
+      rval = eeval.integrate(&integral);
 #ifndef NDEBUG
-    if (MB_SUCCESS != rval) return rval;
+      if (MB_SUCCESS != rval) return rval;
 #endif
+    }
+  }
+  else if (ELEMUTIL == method) {
+    std::vector<CartVect> vcoords(MAX_NODES_PER_ELEMENT);
+    std::vector<double> tagval(MAX_NODES_PER_ELEMENT);
+    const EntityHandle *connect;
+    int nconn;
+    Element::Map *elemmap = NULL;
+    for (rit = elems.begin(), i = 0; rit != elems.end(); rit++, i++) {
+      rval = mbi.get_connectivity(*rit, connect, nconn); CHK(rval, "get_connectivity");
+      rval = mbi.get_coords(connect, nconn, vcoords[0].array()); CHK(rval, "get_coords");
+      rval = get_elem_map(mbi.type_from_handle(*rit), vcoords, nconn, elemmap); CHK(rval, "get_elem_map");
+      rval = mbi.tag_get_data(tag, connect, nconn, tagval.data()); CHK(rval, "tag_get_data");
+      integral = elemmap->integrate_scalar_field(tagval.data());
+    }
   }
   inttime = mytime() - inttime;
   return MB_SUCCESS;
@@ -154,6 +232,46 @@ ErrorCode put_random_field(Interface &mbi, Tag &tag, Range &elems)
   return rval;
 }
 
+ErrorCode new_elem_evals(Interface &mbi, Range &elems, std::vector<CartVect> &params,
+                         double &evtime, double &retime, double &jactime, double &inttime) 
+{
+  evtime = 0, retime = 0, jactime = 0, inttime = 0; // initializations to avoid compiler warning
+  
+    // time/test forward evaluation, putting results into vector
+  rval = time_forward_eval(eeval, elems, params, coords, evtime); CHK(rval, "time_forward_eval");
+
+    // time/test reverse evaluation, putting results into vector
+  rval = time_reverse_eval(eeval, elems, coords, params, retime); CHK(rval, "time_reverse_eval");
+
+    // time/test Jacobian evaluation
+  rval = time_jacobian(eeval, elems, params, jactime); CHK(rval, "time_jacobian");
+
+    // time/test integration
+  rval = time_integrate(eeval, tag, elems, inttime); CHK(rval, "time_integrate");
+
+  return rval;
+}
+
+ErrorCode old_elem_evals(Interface &mbi, Range &elems, std::vector<CartVect> &params,
+                         double &evtime, double &retime, double &jactime, double &inttime) 
+{
+  evtime = 0, retime = 0, jactime = 0, inttime = 0; // initializations to avoid compiler warning
+  
+    // time/test forward evaluation, putting results into vector
+  rval = time_forward_eval(eeval, elems, params, coords, evtime); CHK(rval, "time_forward_eval");
+
+    // time/test reverse evaluation, putting results into vector
+  rval = time_reverse_eval(eeval, elems, coords, params, retime); CHK(rval, "time_reverse_eval");
+
+    // time/test Jacobian evaluation
+  rval = time_jacobian(eeval, elems, params, jactime); CHK(rval, "time_jacobian");
+
+    // time/test integration
+  rval = time_integrate(eeval, tag, elems, inttime); CHK(rval, "time_integrate");
+
+  return rval;
+}
+
 int main( int argc, char* argv[] )
 {
     // parse options
@@ -183,32 +301,18 @@ int main( int argc, char* argv[] )
     if (dim > 2) params[i][2] = -1 + 2*((double)rand())/RAND_MAX;
   }
 
-    // construct ElemEvaluator
-  EvalSet eset;
-  ElemEvaluator eeval(&mbi);
-  eeval.set_eval_set(*elems.begin());
-  eeval.set_tag_handle(0, 0); // indicates coordinates as the field to evaluate
-  
-  double evtime = 0, retime = 0, jactime = 0, inttime = 0; // initializations to avoid compiler warning
-  
-    // time/test forward evaluation, putting results into vector
-  rval = time_forward_eval(eeval, elems, params, coords, evtime); CHK(rval, "time_forward_eval");
-
-    // time/test reverse evaluation, putting results into vector
-  rval = time_reverse_eval(eeval, elems, coords, params, retime); CHK(rval, "time_reverse_eval");
-
-    // time/test Jacobian evaluation
-  rval = time_jacobian(eeval, elems, params, jactime); CHK(rval, "time_jacobian");
-
     // put random field on vertices
   Tag tag;
   rval = put_random_field(mbi, tag, elems);
+  CHK(rval, "put_random_field");
 
-    // time/test integration
-  rval = time_integrate(eeval, tag, elems, inttime); CHK(rval, "time_integrate");
-
+  rval = new_elem_evals(mbi, elems, params,
+                        evtime, retime, jactime, inttime);
+  CHK(rval, "new_elem_evals");
+  
   std::cout << filename << ": " << elems.size() << " " << CN::EntityTypeName(tp)
-            << " elements, " << nv << " vertices per element." << std::endl;
+            << " elements, " << nv << " vertices per element." << std::endl << std::endl;
+  std::cout << "New element evaluation code:" << std::endl;
   std::cout << "Evaluation type, time, time per element:" << std::endl;
   std::cout << "Forward evaluation " << evtime << ", " << evtime / elems.size() << std::endl;
   std::cout << "Reverse evaluation " << retime << ", " << retime / elems.size() << std::endl;

This diff is so big that we needed to truncate the remainder.

https://bitbucket.org/fathomteam/moab/commits/34b8e5c98228/
Changeset:   34b8e5c98228
Branch:      None
User:        tautges
Date:        2013-03-21 18:49:52
Summary:     Was passing wrong argument to inside_nat_space.

make check now passes for mbcoupler_test, yay!

Affected #:  1 file

diff --git a/tools/mbcoupler/Coupler.cpp b/tools/mbcoupler/Coupler.cpp
index 23157d1..187a992 100644
--- a/tools/mbcoupler/Coupler.cpp
+++ b/tools/mbcoupler/Coupler.cpp
@@ -711,7 +711,7 @@ ErrorCode Coupler::nat_param(double xyz[3],
         {
           Element::LinearHex hexmap(coords_vert);
           tmp_nat_coords = hexmap.ievaluate(CartVect(xyz), epsilon);
-          bool inside = hexmap.inside_nat_space(CartVect(xyz), epsilon);
+          bool inside = hexmap.inside_nat_space(tmp_nat_coords, epsilon);
           if (!inside)
             continue;
         }
@@ -719,7 +719,7 @@ ErrorCode Coupler::nat_param(double xyz[3],
         {
           Element::QuadraticHex hexmap(coords_vert);
           tmp_nat_coords = hexmap.ievaluate(CartVect(xyz), epsilon);
-          bool inside = hexmap.inside_nat_space(CartVect(xyz), epsilon);
+          bool inside = hexmap.inside_nat_space(tmp_nat_coords, epsilon);
           if (!inside)
             continue;
         }
@@ -729,7 +729,7 @@ ErrorCode Coupler::nat_param(double xyz[3],
       else if (etype == MBTET){
         Element::LinearTet tetmap(coords_vert);
         tmp_nat_coords = tetmap.ievaluate(CartVect(xyz));
-        bool inside = tetmap.inside_nat_space(CartVect(xyz), epsilon);
+        bool inside = tetmap.inside_nat_space(tmp_nat_coords, epsilon);
         if (!inside)
           continue;
       }
@@ -737,7 +737,7 @@ ErrorCode Coupler::nat_param(double xyz[3],
         Element::LinearQuad quadmap(coords_vert);
         try {
           tmp_nat_coords = quadmap.ievaluate(CartVect(xyz), epsilon);
-          bool inside = quadmap.inside_nat_space(CartVect(xyz), epsilon);
+          bool inside = quadmap.inside_nat_space(tmp_nat_coords, epsilon);
           if (!inside) continue;
         }
         catch (Element::Map::EvaluationError) {


https://bitbucket.org/fathomteam/moab/commits/d8a752f1adac/
Changeset:   d8a752f1adac
Branch:      None
User:        tautges
Date:        2013-03-21 21:24:39
Summary:     Adding equivalent calls to the ElemUtil-based functions, for comparison.
Tightening the implementation in ElemUtil regarding virtual functions and inlined functions
  (not really needed, but was chasing unresolved externals errors).

Affected #:  4 files

diff --git a/test/perf/point_location/Makefile.am b/test/perf/point_location/Makefile.am
index 3590d6a..f34f41d 100644
--- a/test/perf/point_location/Makefile.am
+++ b/test/perf/point_location/Makefile.am
@@ -8,7 +8,7 @@ AM_CPPFLAGS += -I$(top_srcdir)/src \
                -I$(top_srcdir)/src/moab/point_locator/lotte \
                -DIS_BUILDING_MB
             
-LDADD = $(top_builddir)/src/libMOAB.la
+LDADD = $(top_builddir)/src/libMOAB.la $(top_builddir)/tools/mbcoupler/libmbcoupler.la
 
 check_PROGRAMS = 
 noinst_PROGRAMS = point_location elem_eval_time

diff --git a/test/perf/point_location/elem_eval_time.cpp b/test/perf/point_location/elem_eval_time.cpp
index 2507616..ea08956 100644
--- a/test/perf/point_location/elem_eval_time.cpp
+++ b/test/perf/point_location/elem_eval_time.cpp
@@ -3,6 +3,7 @@
 #include "moab/ProgOptions.hpp"
 #include "moab/CartVect.hpp"
 #include "moab/ElemEvaluator.hpp"
+#include "moab/CN.hpp"
 #include "ElemUtil.hpp"
 #include <iostream>
 #include <time.h>
@@ -25,6 +26,8 @@ extern "C" int getrusage(int, struct rusage *);
 using namespace moab;
 #define CHK(r,s) do { if (MB_SUCCESS != (r)) {fail( (r), (s), __FILE__, __LINE__ ); return (r);}} while(false)
 
+const int ELEMEVAL = 0, ELEMUTIL = 1;
+
 static void fail( ErrorCode error_code, const char *str, const char* file_name, int line_number )
 {
   std::cerr << str << ", line " << line_number << " of file " << file_name << ", error code " << error_code << std::endl;
@@ -67,7 +70,39 @@ void parse_options(ProgOptions &opts, int &dim, std::string &filename)
   opts.addOpt<std::string>(std::string("filename,f"), std::string("Filename containing mesh"), &filename);
 }
 
-ErrorCode time_forward_eval(Interface &mbi, int method, Range &elems, 
+ErrorCode get_elem_map(EntityType tp, std::vector<CartVect> &vcoords, int nconn, Element::Map *&elemmap) 
+{
+  switch (tp) {
+    case MBHEX:
+        if (nconn == 8) {
+          elemmap = new Element::LinearHex(vcoords);
+          break;
+        }
+        else if (nconn == 27) {
+          elemmap = new Element::QuadraticHex(vcoords);
+          break;
+        }
+        else return MB_FAILURE;
+    case MBTET:
+        if (nconn == 4) {
+          elemmap = new Element::LinearTet(vcoords);
+          break;
+        }
+        else return MB_FAILURE;
+    case MBQUAD:
+        if (nconn == 4) {
+          elemmap = new Element::LinearQuad(vcoords);
+          break;
+        }
+        else return MB_FAILURE;
+    default:
+        return MB_FAILURE;
+  }
+  
+  return MB_SUCCESS;
+}
+
+ErrorCode time_forward_eval(Interface *mbi, int method, Range &elems, 
                             std::vector<CartVect> &params, std::vector<CartVect> &coords, 
                             double &evtime) 
 {
@@ -78,7 +113,7 @@ ErrorCode time_forward_eval(Interface &mbi, int method, Range &elems,
   if (ELEMEVAL == method) {
       // construct ElemEvaluator
     EvalSet eset;
-    ElemEvaluator eeval(&mbi);
+    ElemEvaluator eeval(mbi);
     eeval.set_eval_set(*elems.begin());
     eeval.set_tag_handle(0, 0); // indicates coordinates as the field to evaluate
   
@@ -91,14 +126,14 @@ ErrorCode time_forward_eval(Interface &mbi, int method, Range &elems,
     }
   }
   else if (ELEMUTIL == method) {
-    std::vector<CartVect> vcoords(MAX_NODES_PER_ELEMENT);
+    std::vector<CartVect> vcoords(CN::MAX_NODES_PER_ELEMENT);
     const EntityHandle *connect;
     int nconn;
     Element::Map *elemmap = NULL;
     for (rit = elems.begin(), i = 0; rit != elems.end(); rit++, i++) {
-      rval = mbi.get_connectivity(*rit, connect, nconn); CHK(rval, "get_connectivity");
-      rval = mbi.get_coords(connect, nconn, vcoords[0].array()); CHK(rval, "get_coords");
-      rval = get_elem_map(mbi.type_from_handle(*rit), vcoords, nconn, elemmap); CHK(rval, "get_elem_map");
+      rval = mbi->get_connectivity(*rit, connect, nconn); CHK(rval, "get_connectivity");
+      rval = mbi->get_coords(connect, nconn, vcoords[0].array()); CHK(rval, "get_coords");
+      rval = get_elem_map(mbi->type_from_handle(*rit), vcoords, nconn, elemmap); CHK(rval, "get_elem_map");
       coords[i] = elemmap->evaluate(params[i]);
     }
   }
@@ -117,7 +152,7 @@ ErrorCode time_reverse_eval(Interface *mbi, int method, Range &elems,
   unsigned int i;
   if (ELEMEVAL == method) {
     EvalSet eset;
-    ElemEvaluator eeval(&mbi);
+    ElemEvaluator eeval(mbi);
     eeval.set_eval_set(*elems.begin());
     eeval.set_tag_handle(0, 0); // indicates coordinates as the field to evaluate    
     bool ins;
@@ -131,15 +166,15 @@ ErrorCode time_reverse_eval(Interface *mbi, int method, Range &elems,
     }
   }
   else if (ELEMUTIL == method) {
-    std::vector<CartVect> vcoords(MAX_NODES_PER_ELEMENT);
+    std::vector<CartVect> vcoords(CN::MAX_NODES_PER_ELEMENT);
     const EntityHandle *connect;
     int nconn;
     Element::Map *elemmap = NULL;
     for (rit = elems.begin(), i = 0; rit != elems.end(); rit++, i++) {
-      rval = mbi.get_connectivity(*rit, connect, nconn); CHK(rval, "get_connectivity");
-      rval = mbi.get_coords(connect, nconn, vcoords[0].array()); CHK(rval, "get_coords");
-      rval = get_elem_map(mbi.type_from_handle(*rit), vcoords, nconn, elemmap); CHK(rval, "get_elem_map");
-      coords[i] = elemmap->ievaluate(coords[i].array, 1.0e-6);
+      rval = mbi->get_connectivity(*rit, connect, nconn); CHK(rval, "get_connectivity");
+      rval = mbi->get_coords(connect, nconn, vcoords[0].array()); CHK(rval, "get_coords");
+      rval = get_elem_map(mbi->type_from_handle(*rit), vcoords, nconn, elemmap); CHK(rval, "get_elem_map");
+      coords[i] = elemmap->ievaluate(coords[i], 1.0e-6);
     }
   }
   retime = mytime() - retime;
@@ -156,7 +191,7 @@ ErrorCode time_jacobian(Interface *mbi, int method, Range &elems, std::vector<Ca
   Matrix3 jac;
   if (ELEMEVAL == method) {
     EvalSet eset;
-    ElemEvaluator eeval(&mbi);
+    ElemEvaluator eeval(mbi);
     eeval.set_eval_set(*elems.begin());
     eeval.set_tag_handle(0, 0); // indicates coordinates as the field to evaluate    
     for (rit = elems.begin(), i = 0; rit != elems.end(); rit++, i++) {
@@ -168,15 +203,15 @@ ErrorCode time_jacobian(Interface *mbi, int method, Range &elems, std::vector<Ca
     }
   }
   else if (ELEMUTIL == method) {
-    std::vector<CartVect> vcoords(MAX_NODES_PER_ELEMENT);
+    std::vector<CartVect> vcoords(CN::MAX_NODES_PER_ELEMENT);
     const EntityHandle *connect;
     int nconn;
     Element::Map *elemmap = NULL;
     for (rit = elems.begin(), i = 0; rit != elems.end(); rit++, i++) {
-      rval = mbi.get_connectivity(*rit, connect, nconn); CHK(rval, "get_connectivity");
-      rval = mbi.get_coords(connect, nconn, vcoords[0].array()); CHK(rval, "get_coords");
-      rval = get_elem_map(mbi.type_from_handle(*rit), vcoords, nconn, elemmap); CHK(rval, "get_elem_map");
-      jac = elemmap->jacobian(params[i].array());
+      rval = mbi->get_connectivity(*rit, connect, nconn); CHK(rval, "get_connectivity");
+      rval = mbi->get_coords(connect, nconn, vcoords[0].array()); CHK(rval, "get_coords");
+      rval = get_elem_map(mbi->type_from_handle(*rit), vcoords, nconn, elemmap); CHK(rval, "get_elem_map");
+      jac = elemmap->jacobian(params[i]);
     }
   }
   jactime = mytime() - jactime;
@@ -190,7 +225,7 @@ ErrorCode time_integrate(Interface *mbi, int method, Tag tag, Range &elems, doub
   double integral;
   if (ELEMEVAL == method) {
     EvalSet eset;
-    ElemEvaluator eeval(&mbi);
+    ElemEvaluator eeval(mbi);
     eeval.set_eval_set(*elems.begin());
     eeval.set_tag_handle(0, 0); // indicates coordinates as the field to evaluate    
     rval = eeval.set_tag_handle(tag, 0); CHK(rval, "set_tag_handle");
@@ -203,16 +238,18 @@ ErrorCode time_integrate(Interface *mbi, int method, Tag tag, Range &elems, doub
     }
   }
   else if (ELEMUTIL == method) {
-    std::vector<CartVect> vcoords(MAX_NODES_PER_ELEMENT);
-    std::vector<double> tagval(MAX_NODES_PER_ELEMENT);
+    std::vector<CartVect> vcoords(CN::MAX_NODES_PER_ELEMENT);
+    std::vector<double> tagval(CN::MAX_NODES_PER_ELEMENT);
     const EntityHandle *connect;
     int nconn;
     Element::Map *elemmap = NULL;
+    Range::iterator rit;
+    unsigned int i;
     for (rit = elems.begin(), i = 0; rit != elems.end(); rit++, i++) {
-      rval = mbi.get_connectivity(*rit, connect, nconn); CHK(rval, "get_connectivity");
-      rval = mbi.get_coords(connect, nconn, vcoords[0].array()); CHK(rval, "get_coords");
-      rval = get_elem_map(mbi.type_from_handle(*rit), vcoords, nconn, elemmap); CHK(rval, "get_elem_map");
-      rval = mbi.tag_get_data(tag, connect, nconn, tagval.data()); CHK(rval, "tag_get_data");
+      rval = mbi->get_connectivity(*rit, connect, nconn); CHK(rval, "get_connectivity");
+      rval = mbi->get_coords(connect, nconn, vcoords[0].array()); CHK(rval, "get_coords");
+      rval = get_elem_map(mbi->type_from_handle(*rit), vcoords, nconn, elemmap); CHK(rval, "get_elem_map");
+      rval = mbi->tag_get_data(tag, connect, nconn, tagval.data()); CHK(rval, "tag_get_data");
       integral = elemmap->integrate_scalar_field(tagval.data());
     }
   }
@@ -232,42 +269,23 @@ ErrorCode put_random_field(Interface &mbi, Tag &tag, Range &elems)
   return rval;
 }
 
-ErrorCode new_elem_evals(Interface &mbi, Range &elems, std::vector<CartVect> &params,
-                         double &evtime, double &retime, double &jactime, double &inttime) 
-{
-  evtime = 0, retime = 0, jactime = 0, inttime = 0; // initializations to avoid compiler warning
-  
-    // time/test forward evaluation, putting results into vector
-  rval = time_forward_eval(eeval, elems, params, coords, evtime); CHK(rval, "time_forward_eval");
-
-    // time/test reverse evaluation, putting results into vector
-  rval = time_reverse_eval(eeval, elems, coords, params, retime); CHK(rval, "time_reverse_eval");
-
-    // time/test Jacobian evaluation
-  rval = time_jacobian(eeval, elems, params, jactime); CHK(rval, "time_jacobian");
-
-    // time/test integration
-  rval = time_integrate(eeval, tag, elems, inttime); CHK(rval, "time_integrate");
-
-  return rval;
-}
-
-ErrorCode old_elem_evals(Interface &mbi, Range &elems, std::vector<CartVect> &params,
-                         double &evtime, double &retime, double &jactime, double &inttime) 
+ErrorCode elem_evals(Interface *mbi, int method, Range &elems, Tag tag,
+                     std::vector<CartVect> &params, std::vector<CartVect> &coords, 
+                     double &evtime, double &retime, double &jactime, double &inttime) 
 {
   evtime = 0, retime = 0, jactime = 0, inttime = 0; // initializations to avoid compiler warning
   
     // time/test forward evaluation, putting results into vector
-  rval = time_forward_eval(eeval, elems, params, coords, evtime); CHK(rval, "time_forward_eval");
+  ErrorCode rval = time_forward_eval(mbi, method, elems, params, coords, evtime); CHK(rval, "time_forward_eval");
 
     // time/test reverse evaluation, putting results into vector
-  rval = time_reverse_eval(eeval, elems, coords, params, retime); CHK(rval, "time_reverse_eval");
+  rval = time_reverse_eval(mbi, method, elems, coords, params, retime); CHK(rval, "time_reverse_eval");
 
     // time/test Jacobian evaluation
-  rval = time_jacobian(eeval, elems, params, jactime); CHK(rval, "time_jacobian");
+  rval = time_jacobian(mbi, method, elems, params, jactime); CHK(rval, "time_jacobian");
 
     // time/test integration
-  rval = time_integrate(eeval, tag, elems, inttime); CHK(rval, "time_integrate");
+  rval = time_integrate(mbi, method, tag, elems, inttime); CHK(rval, "time_integrate");
 
   return rval;
 }
@@ -305,19 +323,33 @@ int main( int argc, char* argv[] )
   Tag tag;
   rval = put_random_field(mbi, tag, elems);
   CHK(rval, "put_random_field");
+  double evtime[2], retime[2], jactime[2], inttime[2]; // initializations to avoid compiler warning
 
-  rval = new_elem_evals(mbi, elems, params,
-                        evtime, retime, jactime, inttime);
-  CHK(rval, "new_elem_evals");
+  rval = elem_evals(&mbi, ELEMEVAL, elems, tag, params, coords,
+                    evtime[0], retime[0], jactime[0], inttime[0]);
+  CHK(rval, "new elem_evals");
+  
+  rval = elem_evals(&mbi, ELEMUTIL, elems, tag, params, coords, 
+                    evtime[1], retime[1], jactime[1], inttime[1]);
+  CHK(rval, "old elem_evals");
   
   std::cout << filename << ": " << elems.size() << " " << CN::EntityTypeName(tp)
             << " elements, " << nv << " vertices per element." << std::endl << std::endl;
-  std::cout << "New element evaluation code:" << std::endl;
+  std::cout << "New, old element evaluation code:" << std::endl;
   std::cout << "Evaluation type, time, time per element:" << std::endl;
-  std::cout << "Forward evaluation " << evtime << ", " << evtime / elems.size() << std::endl;
-  std::cout << "Reverse evaluation " << retime << ", " << retime / elems.size() << std::endl;
-  std::cout << "Jacobian           " << jactime << ", " << jactime / elems.size() << std::endl;
-  std::cout << "Integration        " << inttime << ", " << inttime / elems.size() << std::endl;
+  std::cout << "                New                   Old            (New-Old)/Old" << std::endl;
+  std::cout << "Forward evaluation " << evtime[0] << ", " << evtime[0] / elems.size()
+            << "    " << evtime[1] << ", " << evtime[1] / elems.size() 
+            << ", " << (evtime[0]-evtime[1])/(evtime[0]?evtime[0]:1) << std::endl;
+  std::cout << "Reverse evaluation " << retime[0] << ", " << retime[0] / elems.size()
+            << "    " << retime[1] << ", " << retime[1] / elems.size() 
+            << ", " << (retime[0]-retime[1])/(retime[0]?retime[0]:1) << std::endl;
+  std::cout << "Jacobian           " << jactime[0] << ", " << jactime[0] / elems.size()
+            << "    " << jactime[1] << ", " << jactime[1] / elems.size() 
+            << ", " << (jactime[0]-jactime[1])/(jactime[0]?jactime[0]:1) << std::endl;
+  std::cout << "Integration        " << inttime[0] << ", " << inttime[0] / elems.size()
+            << "    " << inttime[1] << ", " << inttime[1] / elems.size() 
+            << ", " << (inttime[0]-inttime[1])/(inttime[0]?inttime[0]:1) << std::endl;
   
 }
 

diff --git a/tools/mbcoupler/ElemUtil.cpp b/tools/mbcoupler/ElemUtil.cpp
index 4ebda42..0a856ed 100644
--- a/tools/mbcoupler/ElemUtil.cpp
+++ b/tools/mbcoupler/ElemUtil.cpp
@@ -420,19 +420,20 @@ bool integrate_trilinear_hex(const CartVect* hex_corners,
 
 namespace Element {
 
+    Map::~Map() 
+    {}
+    
+      const std::vector<CartVect>& Map::get_vertices() {
+        return this->vertex;
+      }
+        //
+      void Map::set_vertices(const std::vector<CartVect>& v) {
+        if(v.size() != this->vertex.size()) {
+          throw ArgError();
+        }
+        this->vertex = v;
+      }
 
-  
-  inline const std::vector<CartVect>& Map::get_vertices() {
-    return this->vertex;
-  }
-  //
-  void Map::set_vertices(const std::vector<CartVect>& v) {
-    if(v.size() != this->vertex.size()) {
-      throw ArgError();
-    }
-    this->vertex = v;
-  }// Map::set_vertices()
-  //
   CartVect Map::ievaluate(const CartVect& x, double tol, const CartVect& x0) const {
     // TODO: should differentiate between epsilons used for
     // Newton Raphson iteration, and epsilons used for curved boundary geometry errors
@@ -475,6 +476,8 @@ namespace Element {
 
   }// LinearHex::LinearHex()
 
+    LinearHex::~LinearHex() 
+    {}
   /* For each point, its weight and location are stored as an array.
      Hence, the inner dimension is 2, the outer dimension is gauss_count.
      We use a one-point Gaussian quadrature, since it integrates linear functions exactly.
@@ -590,6 +593,8 @@ namespace Element {
   QuadraticHex::QuadraticHex():Map(0) {
   }
 
+    QuadraticHex::~QuadraticHex() 
+    {}
   double SH(const int i, const double xi)
   {
     switch (i)
@@ -686,6 +691,9 @@ namespace Element {
   }// LinearTet::LinearTet()
 
 
+    LinearTet::~LinearTet() 
+    {}
+
   void LinearTet::set_vertices(const std::vector<CartVect>& v) {
     this->Map::set_vertices(v);
     this->T = Matrix3(v[1][0]-v[0][0],v[2][0]-v[0][0],v[3][0]-v[0][0],
@@ -939,6 +947,9 @@ namespace Element {
 
   }// LinearQuad::LinearQuad()
 
+    LinearQuad::~LinearQuad() 
+    {}
+    
   /* For each point, its weight and location are stored as an array.
      Hence, the inner dimension is 2, the outer dimension is gauss_count.
      We use a one-point Gaussian quadrature, since it integrates linear functions exactly.

diff --git a/tools/mbcoupler/ElemUtil.hpp b/tools/mbcoupler/ElemUtil.hpp
index 34b2af8..a822621 100644
--- a/tools/mbcoupler/ElemUtil.hpp
+++ b/tools/mbcoupler/ElemUtil.hpp
@@ -70,11 +70,11 @@ namespace ElemUtil {
       Map(const std::vector<CartVect>& v) {this->vertex.resize(v.size()); this->set_vertices(v);};
       /**\brief Construct a Map defined by n vertices. */
       Map(const unsigned int n) {this->vertex = std::vector<CartVect>(n);};
-      virtual ~Map() {};
+      virtual ~Map();
       /**\brief Evaluate the map on \xi (calculate $\vec x = F($\vec \xi)$ )*/
       virtual CartVect evaluate( const CartVect& xi ) const = 0;
       /**\brief Evaluate the inverse map (calculate $\vec \xi = F^-1($\vec x)$ to given tolerance)*/
-      CartVect ievaluate( const CartVect& x, double tol, const CartVect& x0 = CartVect(0.0)) const ;
+      virtual CartVect ievaluate( const CartVect& x, double tol, const CartVect& x0 = CartVect(0.0)) const ;
       /**\brief decide if within the natural param space, with a tolerance*/
       virtual bool inside_nat_space(const CartVect & xi, double & tol) const = 0;
       /* FIX: should evaluate and ievaluate return both the value and the Jacobian (first jet)? */
@@ -98,7 +98,7 @@ namespace ElemUtil {
       /**\brief Size of the vertices vector. */
       unsigned int size() {return this->vertex.size();}
       /**\brief Retrieve vertices. */
-      inline const std::vector<CartVect>& get_vertices();
+      const std::vector<CartVect>& get_vertices();
       /**\brief Set vertices.      */
       virtual void set_vertices(const std::vector<CartVect>& v);
       
@@ -122,13 +122,15 @@ namespace ElemUtil {
     public:
       LinearHex(const std::vector<CartVect>& vertices) : Map(vertices){};
       LinearHex();
+      virtual ~LinearHex();
+      
       virtual CartVect evaluate( const CartVect& xi ) const;
       //virtual CartVect ievaluate(const CartVect& x, double tol) const ;
       virtual bool inside_nat_space(const CartVect & xi, double & tol) const;
 
       virtual Matrix3  jacobian(const CartVect& xi) const;
-      double   evaluate_scalar_field(const CartVect& xi, const double *field_vertex_values) const;
-      double   integrate_scalar_field(const double *field_vertex_values) const;
+      virtual double   evaluate_scalar_field(const CartVect& xi, const double *field_vertex_values) const;
+      virtual double   integrate_scalar_field(const double *field_vertex_values) const;
 
     protected:
       /* Preimages of the vertices -- "canonical vertices" -- are known as "corners". */
@@ -144,13 +146,14 @@ namespace ElemUtil {
     public:
       QuadraticHex(const std::vector<CartVect>& vertices) : Map(vertices){};
       QuadraticHex();
+      virtual ~QuadraticHex();
       virtual CartVect evaluate( const CartVect& xi ) const;
       //virtual CartVect ievaluate(const CartVect& x, double tol) const ;
       virtual bool inside_nat_space(const CartVect & xi, double & tol) const;
 
       virtual Matrix3  jacobian(const CartVect& xi) const;
-      double   evaluate_scalar_field(const CartVect& xi, const double *field_vertex_values) const;
-      double   integrate_scalar_field(const double *field_vertex_values) const;
+      virtual double   evaluate_scalar_field(const CartVect& xi, const double *field_vertex_values) const;
+      virtual double   integrate_scalar_field(const double *field_vertex_values) const;
 
     protected:
       /* Preimages of the vertices -- "canonical vertices" -- are known as "corners".
@@ -166,6 +169,7 @@ namespace ElemUtil {
     public:
       LinearTet(const std::vector<CartVect>& vertices) : Map(vertices){};
       LinearTet();
+      virtual ~LinearTet();
       /* Override the evaluation routines to take advantage of the properties of P1. */
       virtual CartVect evaluate(const CartVect& xi) const {return this->vertex[0] + this->T*xi;};
       virtual CartVect ievaluate(const CartVect& x) const {return this->T_inverse*(x-this->vertex[0]);};
@@ -174,12 +178,12 @@ namespace ElemUtil {
       virtual double   det_jacobian(const CartVect& )  const {return this->det_T;};
       virtual double   det_ijacobian(const CartVect& ) const {return this->det_T_inverse;};
       //
-      double   evaluate_scalar_field(const CartVect& xi, const double *field_vertex_values) const;
-      double   integrate_scalar_field(const double *field_vertex_values) const;
+      virtual double   evaluate_scalar_field(const CartVect& xi, const double *field_vertex_values) const;
+      virtual double   integrate_scalar_field(const double *field_vertex_values) const;
       //
       /* Override set_vertices so we can precompute the matrices effecting the mapping to and from the canonical simplex. */
-      void     set_vertices(const std::vector<CartVect>& v);
-      bool inside_nat_space(const CartVect & xi, double & tol) const;
+      virtual void     set_vertices(const std::vector<CartVect>& v);
+      virtual bool inside_nat_space(const CartVect & xi, double & tol) const;
     protected:
       static const double corner[4][3];
       Matrix3 T, T_inverse;
@@ -225,13 +229,14 @@ namespace ElemUtil {
     public:
       LinearQuad(const std::vector<CartVect>& vertices) : Map(vertices){};
       LinearQuad();
+      virtual ~LinearQuad();
       virtual CartVect evaluate( const CartVect& xi ) const;
       //virtual CartVect ievaluate(const CartVect& x, double tol) const ;
       virtual bool inside_nat_space(const CartVect & xi, double & tol) const;
 
       virtual Matrix3  jacobian(const CartVect& xi) const;
-      double   evaluate_scalar_field(const CartVect& xi, const double *field_vertex_values) const;
-      double   integrate_scalar_field(const double *field_vertex_values) const;
+      virtual double   evaluate_scalar_field(const CartVect& xi, const double *field_vertex_values) const;
+      virtual double   integrate_scalar_field(const double *field_vertex_values) const;
 
     protected:
       /* Preimages of the vertices -- "canonical vertices" -- are known as "corners". */
@@ -247,13 +252,14 @@ namespace ElemUtil {
     public:
       HOEdge(const std::vector<CartVect>& vertices) : Map(vertices){};
       HOEdge();
+      virtual ~HOEdge();
       virtual CartVect evaluate( const CartVect& xi ) const;
       //virtual CartVect ievaluate(const CartVect& x, double tol) const ;
       virtual bool inside_nat_space(const CartVect & xi, double & tol) const;
 
       virtual Matrix3  jacobian(const CartVect& xi) const;
-      double   evaluate_scalar_field(const CartVect& xi, const double *field_vertex_values) const;
-      double   integrate_scalar_field(const double *field_vertex_values) const;
+      virtual double   evaluate_scalar_field(const CartVect& xi, const double *field_vertex_values) const;
+      virtual double   integrate_scalar_field(const double *field_vertex_values) const;
 
     protected:
       /* Preimages of the vertices -- "canonical vertices" -- are known as "corners". */


https://bitbucket.org/fathomteam/moab/commits/30ea67dc599b/
Changeset:   30ea67dc599b
Branch:      None
User:        tautges
Date:        2013-04-29 20:56:37
Summary:     Merging .gitignore info, sorting it to aid removing duplicates.

Affected #:  1 file

diff --git a/.gitignore b/.gitignore
index 3181e16..8569087 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,176 +1,234 @@
-MOABConfig.cmake
+*~
+*.a
 aclocal.m4
 autom4te.cache/
-config.h
-config.h.in
-config.log
-config.lt
-config.status
+bin
+bin/*
+*.ccm
 config/config.guess
 config/config.sub
 config/depcomp
+config.h
+config.h.in
 config/install-sh
 config/libtool.m4
+config.log
+config.lt
 config/ltmain.sh
+config/lt~obsolete.m4
 config/ltoptions.m4
 config/ltsugar.m4
 config/ltversion.m4
-config/lt~obsolete.m4
 config/missing
+config.status
+config/test-driver
 configure
+.cproject
+*.cub
+.deps
 doc/config.tex
 doc/dev.dox
+doc/user/*
 doc/user.dox
 examples/examples.make
-itaps/iBase_f.h
-itaps/igeom/FBiGeom-Defs.inc
-itaps/imesh/iMesh-Defs.inc
-itaps/imesh/iMeshP_extensions_protos.h
-itaps/imesh/iMeshP_protos.h
-itaps/imesh/iMesh_extensions_protos.h
-itaps/imesh/iMesh_protos.h
-libtool
-moab.make
-src/FCDefs.h
-src/MBCN_protos.h
-src/MOAB_FCDefs.h
-src/moab/EntityHandle.hpp
-src/moab/Version.h
-src/moab/stamp-h2
-src/moab/stamp-h3
-src/parallel/moab_mpi_config.h
-src/parallel/stamp-h4
-src/stamp-h5
-stamp-h1
-tools/mbcoupler/tests/
-tools/mbzoltan/Config.moab
-tools/vtkMOABReader/CMakeLists.txt
-tools/vtkMOABReaderNew/CMakeLists.txt
-.deps
-Makefile.in
-Makefile
-*/Makefile.in
-*/Makefile
-*/**/Makefile.in
-*/**/Makefile
-makefile
-include
-lib
-bin
-*.o
-*.a
-*.la
-*.lai
-*.lo
-*.log
-*~
-*.rej
-.libs
-diffs
-src/io/mhdf/h5minfo
-src/io/mhdf/h5mvalidate
 examples/FileRead
 examples/GeomSetHierarchy
-examples/KDTree
 examples/GetEntities
-examples/ObbTree
-examples/SetsNTags
-examples/SkinMesh
-examples/SurfArea
+examples/*.h5m
+examples/HelloMoabPar
 examples/itaps/FindConnectF
 examples/itaps/ListSetsNTagsCXX
 examples/itaps/ListSetsNTagsF90
 examples/itaps/TagIterateC
 examples/itaps/TagIterateF
+examples/KDTree
+examples/ObbTree
+examples/ReduceExchangeTags
+examples/SetsNTags
+examples/SkinMesh
+examples/SurfArea
+examples/TestExodusII
+include
+include/*
+itaps/iBase_f.h
+itaps/igeom/FBiGeom-Defs.inc
+itaps/igeom/FBiGeom_protos.h
+itaps/igeom/testgeom
+itaps/igeom/testSmooth2
+itaps/igeom/testSmoothGeom
 itaps/imesh/FindAdjacencyF90
+itaps/imesh/iMesh-Defs.inc
+itaps/imesh/iMesh_extensions_protos.h
+itaps/imesh/iMeshP_extensions_protos.h
+itaps/imesh/iMeshP_protos.h
+itaps/imesh/iMesh_protos.h
 itaps/imesh/MOAB_iMesh_extensions_tests
+itaps/imesh/MOAB_iMeshP_unit_tests
 itaps/imesh/MOAB_iMesh_unit_tests
+itaps/imesh/partest
 itaps/imesh/ScdMeshF77
 itaps/imesh/ScdMeshF90
 itaps/imesh/testc_cbind
+*.la
+*.la
+*.lai
+lib
+lib/*
+.libs
+libtool
+*.lo
+*.log
+makefile
+Makefile
+*/Makefile
+*/**/Makefile
+*/**/Makefile.in
+*/Makefile.in
+Makefile.in
 moab.config
+MOABConfig.cmake
+moab.creator*
+moab.files
+moab.includes
+moab.make
+*.o
+.project
+*.rej
+share/*
 share/doc/moab
 share/man/man1
-test/mbfacet_test
+*.so
+src/FCDefs.h
+src/io/mhdf/h5minfo
+src/io/mhdf/h5mvalidate
+src/MBCN_protos.h
+src/moab/EntityHandle.hpp
+src/MOAB_FCDefs.h
+src/moab/stamp-h2
+src/moab/stamp-h3
+src/moab/Version.h
+src/parallel/moab_mpi_config.h
+src/parallel/stamp-h4
+src/stamp-h5
+stamp-h1
+test/adaptive_kd_tree_tests
+test/bsp_tree_poly_test
+test/bsp_tree_test
 test/CMakeLists.txt
+test/coords_connect_iterate
+test/cropvol_test
+test/dual/dual_test
 test/elem_eval_test
-test/scdseq_test
 test/file_options_test
-test/kd_tree_test
-test/h5file/h5regression
-test/h5file/h5legacy
+test/*.g
+test/*.g
+test/*.gen
+test/*.gen
+test/geom_util_test
+test/gttool_test
+test/gttool_test
 test/h5file/dump_sets
-test/h5file/h5portable
+test/h5file/h5legacy
 test/h5file/h5partial
+test/h5file/h5portable
+test/h5file/h5regression
 test/h5file/h5sets_test
-test/h5file/h5varlen
 test/h5file/h5test
-test/mesh_set_test
+test/h5file/h5varlen
+test/homxform_test
+test/io/*.ccmg
+test/io/ccmio_test
+test/io/cub_file_test
+test/io/exodus_test
+test/io/*.g
+test/io/gmsh_test
+test/io/ideas_test
+test/io/nastran_test
+test/io/read_cgm_test
+test/io/read_nc
+test/io/read_ucd_nc
+test/io/readutil_test
+test/io/smf_test
+test/io/stl_test
+test/io/tqdcfr
+test/io/vtk_test
+test/kd_tree_test
 test/kd_tree_time
-test/var_len_test_no_template
-test/moab_test
 test/kd_tree_tool
-test/oldinc/test_oldinc
+test/mbcn_test
+test/mbfacet_test
 test/mbground_test
-test/test_prog_opt
-test/seq_man_test
-test/obb/obb_tree_tool
+test/mesh_set_test
+test/moab_test
 test/obb/obb_test
 test/obb/obb_time
-test/reorder_test
-test/homxform_test
-test/bsp_tree_test
-test/tag_test
+test/obb/obb_tree_tool
 test/obb_test
-test/cropvol_test
-test/range_test
-test/gttool_test
-test/test_adj
-test/bsp_tree_poly_test
-test/TestRunner.hpp
-test/xform_test
-test/mbcn_test
-test/adaptive_kd_tree_tests
-test/perf/perftool
-test/perf/tstt_perf_binding
-test/perf/runtest
-test/perf/seqperf
+test/oldinc/test_oldinc
+test/parallel/*.h5m
+test/parallel/mbparallelcomm_test
+test/parallel/mhdf_parallel
+test/parallel/parallel_hdf5_test
+test/parallel/parallel_write_test
+test/parallel/par_coupler_test
+test/parallel/par_intx_sph
+test/parallel/parmerge
+test/parallel/partcheck
+test/parallel/pcomm_serial
+test/parallel/pcomm_unit
+test/parallel/read_nc_par
+test/parallel/scdpart
+test/parallel/scdtest
+test/parallel/structured3
+test/parallel/uber_parallel_test
+test/parallel/ucdtrvpart
+test/parallel/*.vtk
 test/perf/adj_time
 test/perf/perf
+test/perf/perftool
 test/perf/point_in_elem
-test/io/ideas_test
-test/io/read_ucd_nc
-test/io/exodus_test
-test/io/read_nc
-test/io/smf_test
-test/io/tqdcfr
-test/io/cub_file_test
-test/io/nastran_test
-test/io/stl_test
-test/io/gmsh_test
-test/io/readutil_test
-test/io/ccmio_test
-test/io/vtk_test
-test/dual/dual_test
-test/coords_connect_iterate
+test/perf/runtest
+test/perf/seqperf
+test/perf/tstt_perf_binding
+test/range_test
+test/reorder_test
+test/scdseq_test
+test/seq_man_test
+test/tag_test
+test/test_adj
+test/test_prog_opt
+test/TestRunner.hpp
 test/var_len_test
-test/geom_util_test
-tools/mbdepth
-tools/mbgsets
-tools/mbmem
-tools/mbsurfplot
-tools/mbsize
-tools/mbconvert
+test/var_len_test_no_template
+test/xform_test
 tools/dagmc/dagmc_preproc
 tools/dagmc/pt_vol_test
+tools/dagmc/quads_to_tris
 tools/dagmc/ray_fire_test
 tools/dagmc/test_geom
-tools/dagmc/quads_to_tris
-tools/spheredecomp
+tools/dagmc/update_coords
+tools/hexmodops
+tools/mbconvert
+tools/mbcoupler/*.h5m
+tools/mbcoupler/tests/
+tools/mbcslam/case1_test
+tools/mbcslam/intersect1.h5m
+tools/mbcslam/intx1.vtk
+tools/mbcslam/intx_in_plane_test
+tools/mbcslam/intx_on_sphere_test
+tools/mbcslam/intx.vtk
+tools/mbcslam/lagr.h5m
+tools/mbcslam/spectral.vtk
+tools/mbcslam/spec_visu_test
+tools/mbcslam/spherical_area_test
+tools/mbdepth
+tools/mbgsets
+tools/mbmem
+tools/mbsize
 tools/mbskin
+tools/mbsurfplot
 tools/mbtagprop
-tools/hexmodops
-test/*.g
-test/*.gen
-test/io/*.g
-test/io/*.ccmg
+tools/mbzoltan/Config.moab
+tools/spheredecomp
+tools/vtkMOABReader/CMakeLists.txt
+tools/vtkMOABReaderNew/CMakeLists.txt


https://bitbucket.org/fathomteam/moab/commits/75ff2487554f/
Changeset:   75ff2487554f
Branch:      None
User:        tautges
Date:        2013-04-29 21:12:10
Summary:     Changes to overcome conflicts.

Affected #:  3 files

diff --git a/examples/KDTree.cpp b/examples/KDTree.cpp
deleted file mode 100644
index 584fd82..0000000
--- a/examples/KDTree.cpp
+++ /dev/null
@@ -1,154 +0,0 @@
-/* Simple example of use of moab::AdaptiveKDTree class.
-   
-   Given a hexahedral mesh, find the hexahedron containing each
-   input position.
- */
-
-
-#include "moab/Core.hpp"
-#include "moab/AdaptiveKDTree.hpp"
-#include "moab/Range.hpp"
-#include "moab/GeomUtil.hpp"
-
-#include <iostream>
-#include <string>
-
-const double EPSILON = 1e-6; // tolerance to use in intersection checks
-
-// Help with error handling.  Given ErrorCode, print
-// corresponding string and any available message.
-void print_error( moab::Interface& mb, moab::ErrorCode err )
-{
-  std::string message;
-  std::string code;
-  if (moab::MB_SUCCESS != mb.get_last_error( message ))
-    message.clear();
-  code = mb.get_error_string(err);
-  std::cerr << "Error: " << code << std::endl;
-  if (!message.empty())
-    std::cerr << "  " << message << std::endl;
-}
-
-// Print diagnostic info for unexpected failures.
-#define CHKERR(err) do { if (moab::MB_SUCCESS != (err)) { \
-  print_error( mb, (err) ); \
-  std::cerr << "Unexpected failure at: " << __FILE__ << ":" << __LINE__ << std::endl; \
-  return 2; \
-  } } while (false)
-
-// Given an entity set and a point, find the hex contained in the
-// entity set which in turn contains the specified point.  Returns
-// 0 if point is not in any hexahedron.
-moab::EntityHandle hex_containing_point( moab::Interface& mb,
-                                         moab::EntityHandle set,
-                                         const double point[3] );
-
-// Print hex containing point.
-void print_hex( moab::Interface& mb, moab::EntityHandle hex );
-
-
-int main( )
-{
-    // Ask user for file to read
-  std::string filename;
-  std::cout << "Hex mesh file name: ";
-  std::cin >> filename;
-  
-    // Read file into MOAB instance
-  moab::ErrorCode rval;
-  moab::Core moab;
-  moab::Interface& mb = moab;
-  rval = mb.load_file( filename.c_str() );
-  if (moab::MB_SUCCESS != rval) {
-    print_error(mb,rval);
-    std::cerr << filename << ": file load failed" << std::endl;
-    return 1;
-  }
-  
-    // Get all hex elemeents
-  moab::Range elems;
-  rval = mb.get_entities_by_type( 0, moab::MBHEX, elems ); CHKERR(rval);
-  if (elems.empty()) {
-    std::cerr << filename << ": file containd no hexahedra" << std::endl;
-    return 1;
-  }
-  
-    // Build a kD-tree from hex elements
-  moab::EntityHandle tree_root;
-  moab::AdaptiveKDTree tool( &mb );
-  rval = tool.build_tree( elems, &tree_root ); CHKERR(rval);
-  
-    // Loop forever (or until EOF), asking user for a point
-    // to query and printing the hex element containing that
-    // point.
-  for (;;) {
-    double point[3];
-    std::cout << "Point coordinates: ";
-    if (!(std::cin >> point[0] >> point[1] >> point[2]))
-      break;
-  
-    moab::EntityHandle leaf;
-    rval = tool.point_search(point, leaf, NULL,  &tree_root); CHKERR(rval);
-    moab::EntityHandle hex = hex_containing_point( mb, leaf, point );
-    if (0 == hex) 
-      std::cout << "Point is not contained in any hexahedron." << std::endl;
-    else
-      print_hex( mb, hex );
-  }
-  
-  return 0;
-}
-
-moab::EntityHandle hex_containing_point( moab::Interface& mb,
-                                         moab::EntityHandle set,
-                                         const double point[3] )
-{
-  moab::ErrorCode rval;
-  moab::CartVect pt(point); // input location
-  moab::CartVect coords[8]; // coordinates of corners of hexahedron
-  const moab::EntityHandle* conn; // hex connectivity
-  int conn_len;
-  
-    // Get hexes in leaf
-  std::vector<moab::EntityHandle> hexes;
-  rval = mb.get_entities_by_type( set, moab::MBHEX, hexes ); CHKERR(rval);
-
-    // Check which hex the point is in
-  std::vector<moab::EntityHandle>::const_iterator i;
-  for (i = hexes.begin(); i != hexes.end(); ++i) {
-    rval = mb.get_connectivity( *i, conn, conn_len ); CHKERR(rval);
-    rval = mb.get_coords( conn, 8, &coords[0][0] ); CHKERR(rval);
-    if (moab::GeomUtil::point_in_trilinear_hex( coords, pt, EPSILON ))
-      return *i;
-  }
-  
-    // Return 0 if no hex contains point.
-  return 0;  
-}
-
-void print_hex( moab::Interface& mb, moab::EntityHandle hex )
-{
-    // Get MOAB's internal ID for hex element
-  int id = mb.id_from_handle(hex);
-  
-    // Get vertex handles for hex corners
-  const moab::EntityHandle* conn; // hex connectivity
-  int conn_len;
-  mb.get_connectivity( hex, conn, conn_len );
-  
-    // Get coordinates of vertices
-  double coords[3*8]; 
-  mb.get_coords( conn, 8, coords );
-  
-    // Print
-  std::cout << " Point is in hex " << id << " with corners: " << std::endl;
-  for (int i = 0; i < 8; ++i) {
-    std::cout << " (" << coords[3*i] 
-              << ", " << coords[3*i+1] 
-              << ", " << coords[3*i+2] 
-              << ")" << std::endl;
-  }
-}
-
-
-  

diff --git a/examples/Makefile.am b/examples/Makefile.am
index d0a33b9..21e6da3 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -7,7 +7,6 @@
 check_PROGRAMS = FileRead \
                  GeomSetHierarchy \
                  GetEntities \
-                 KDTree \
 		 ObbTree \
                  SetsNTags \
                  SkinMesh \
@@ -28,7 +27,6 @@ GetEntities_SOURCES = simple/GetEntities.cpp
 SetsNTags_SOURCES = SetsNTags.cpp
 SkinMesh_SOURCES = SkinMesh.cpp
 SurfArea_SOURCES = SurfArea.cpp
-KDTree_SOURCES = KDTree.cpp
 ObbTree_SOURCES = ObbTree.cpp
 
 exampledir = ${docdir}/examples
@@ -38,7 +36,6 @@ nobase_example_DATA = \
                GeomSetHierarchy.cpp \
                simple/GetEntities.cpp \
                simple/makefile \
-               KDTree.cpp \
 	       ObbTree.cpp \
                SetsNTags.cpp \
                SkinMesh.cpp \

diff --git a/src/parallel/TupleList.cpp b/src/parallel/TupleList.cpp
index 69c955d..ad5b055 100644
--- a/src/parallel/TupleList.cpp
+++ b/src/parallel/TupleList.cpp
@@ -9,8 +9,6 @@
 
 namespace moab {
 
-  extern void fail(const char *fmt, ...);
-
   void fail(const char *fmt, ...)
   {
     va_list ap;
@@ -63,14 +61,14 @@ namespace moab {
     buffSize = 0;
   }
 
-  TupleList::TupleList(uint mi, uint ml,
-		       uint mul, uint mr, uint max)
+  TupleList::TupleList(uint p_mi, uint p_ml,
+		       uint p_mul, uint p_mr, uint p_max)
   {
     vi = NULL;
     vl = NULL;
     vul = NULL;
     vr = NULL;
-    initialize (mi, ml, mul, mr, max);
+    initialize (p_mi, p_ml, p_mul, p_mr, p_max);
   }
 
   TupleList::TupleList()
@@ -83,12 +81,15 @@ namespace moab {
   }
 
   // Allocates space for the tuple list in memory according to parameters
-  void TupleList::initialize (uint mi, uint ml,
-                              uint mul, uint mr, uint max)
+  void TupleList::initialize (uint p_mi, uint p_ml,
+                              uint p_mul, uint p_mr, uint p_max)
   {
     this->n = 0;
-    this->max = max;
-    this->mi = mi, this->ml = ml, this->mul = mul, this->mr = mr;
+    this->max = p_max;
+    this->mi = p_mi;
+    this->ml = p_ml;
+    this->mul = p_mul;
+    this->mr = p_mr;
     size_t sz;
 
     if (max*mi > 0) {


https://bitbucket.org/fathomteam/moab/commits/06bcd2814dad/
Changeset:   06bcd2814dad
Branch:      None
User:        tautges
Date:        2013-04-29 21:23:52
Summary:     More conflict-related changes.

Affected #:  2 files

diff --git a/tools/mbcoupler/ElemUtil.cpp b/tools/mbcoupler/ElemUtil.cpp
index 0a856ed..a77a550 100644
--- a/tools/mbcoupler/ElemUtil.cpp
+++ b/tools/mbcoupler/ElemUtil.cpp
@@ -5,7 +5,7 @@
 #include "ElemUtil.hpp"
 #include "moab/FindPtFuncs.h"
 
-namespace moab { 
+namespace moab {
 namespace ElemUtil {
 
   bool debug = false;
@@ -130,7 +130,7 @@ bool nat_coords_trilinear_hex( const CartVect* corner_coords,
 void nat_coords_trilinear_hex2(const CartVect hex[8], 
                                const CartVect& xyz,
                                CartVect &ncoords,
-                               double etol)       
+                               double etol)
 
 {
   const int ndim = 3;
@@ -143,15 +143,15 @@ void nat_coords_trilinear_hex2(const CartVect hex[8],
   real *xm[ndim];
   for(int i=0; i<ndim; i++)
     xm[i] = coords + i*nverts;
-    
+
   //stuff hex into coords
   for(int i=0; i<nverts; i++){
     real vcoord[ndim];
     hex[i].get(vcoord);
-   
+
     for(int d=0; d<ndim; d++)
       coords[d*nverts + vertMap[i]] = vcoord[d];
-    
+
   }
 
   double dist = 0.0;
@@ -163,11 +163,11 @@ void nat_coords_trilinear_hex2(const CartVect hex[8],
         ncoords[j] *= 10;
     }
   }
-  
+
 }
-bool point_in_trilinear_hex(const CartVect *hex, 
+bool point_in_trilinear_hex(const CartVect *hex,
                             const CartVect& xyz,
-                            double etol) 
+                            double etol)
 {
   CartVect xi;
   return nat_coords_trilinear_hex( hex, xyz, xi, etol )
@@ -177,11 +177,11 @@ bool point_in_trilinear_hex(const CartVect *hex,
 }
 
 
-bool point_in_trilinear_hex(const CartVect *hex, 
-                            const CartVect& xyz, 
-                            const CartVect& box_min, 
+bool point_in_trilinear_hex(const CartVect *hex,
+                            const CartVect& xyz,
+                            const CartVect& box_min,
                             const CartVect& box_max,
-                            double etol) 
+                            double etol)
 {
     // all values scaled by 2 (eliminates 3 flops)
   const CartVect mid = box_max + box_min;
@@ -216,7 +216,7 @@ void hex_findpt(real *xm[3],
                 int n,
                 CartVect xyz,
                 CartVect &rst,
-                double &dist)       
+                double &dist)
 {
 
   //compute stuff that only depends on the order -- could be cached
@@ -227,7 +227,7 @@ void hex_findpt(real *xm[3],
   //triplicates
   for(int d=0; d<3; d++){
     z[d] = tmalloc(real, n);
-    lobatto_nodes(z[d], n); 
+    lobatto_nodes(z[d], n);
     lagrange_setup(&ld[d], z[d], n);
   }
 
@@ -246,10 +246,10 @@ void hex_findpt(real *xm[3],
   rst = r;
 
   //Clean-up (move to destructor if we decide to cache)
-  opt_free_3(&data);  
-  for(int d=0; d<3; ++d) 
+  opt_free_3(&data);
+  for(int d=0; d<3; ++d)
     lagrange_free(&ld[d]);
-  for(int d=0; d<3; ++d) 
+  for(int d=0; d<3; ++d)
     free(z[d]);
 }
 
@@ -266,23 +266,23 @@ void hex_findpt(real *xm[3],
 void hex_eval(real *field,
 	      int n,
 	      CartVect rstCartVec,
-	      double &value)       
+	      double &value)
 {
   int d;
   real rst[3];
   rstCartVec.get(rst);
 
   //can cache stuff below
-  lagrange_data ld[3]; 
+  lagrange_data ld[3];
   real *z[3];
   for(d=0;d<3;++d){
     z[d] = tmalloc(real, n);
     lobatto_nodes(z[d], n);
     lagrange_setup(&ld[d], z[d], n);
-  } 
+  }
 
   //cut and paste -- see findpt.c
-  const unsigned 
+  const unsigned
     nf = n*n,
     ne = n,
     nw = 2*n*n + 3*n;
@@ -292,7 +292,7 @@ void hex_eval(real *field,
   for(d=0; d<3; d++){
     lagrange_0(&ld[d], rst[d]);
   }
-  
+
   value = tensor_i3(ld[0].J,ld[0].n,
 		    ld[1].J,ld[1].n,
 		    ld[2].J,ld[2].n,
@@ -302,7 +302,7 @@ void hex_eval(real *field,
   //all this could be cached
   for(d=0; d<3; d++){
     free(z[d]);
-    lagrange_free(&ld[d]); 
+    lagrange_free(&ld[d]);
   }
   free(od_work);
 }
@@ -310,7 +310,7 @@ void hex_eval(real *field,
 
 // Gaussian quadrature points for a trilinear hex element.
 // Five 2d arrays are defined.
-// One for the single gaussian point solution, 2 point solution, 
+// One for the single gaussian point solution, 2 point solution,
 // 3 point solution, 4 point solution and 5 point solution.
 // There are 2 columns, one for Weights and the other for Locations
 //                                Weight         Location
@@ -349,7 +349,7 @@ bool integrate_trilinear_hex(const CartVect* hex_corners,
   // Use the correct table of points and locations based on the num_pts parameter
   const double (*g_pts)[2] = 0;
   switch (num_pts) {
-  case 1: 
+  case 1:
     g_pts = gauss_1;
     break;
 
@@ -423,7 +423,7 @@ namespace Element {
     Map::~Map() 
     {}
     
-      const std::vector<CartVect>& Map::get_vertices() {
+    inline const std::vector<CartVect>& Map::get_vertices() {
         return this->vertex;
       }
         //
@@ -460,7 +460,70 @@ namespace Element {
     return xi;
   }// Map::ievaluate()
 
+// filescope for static member data that is cached
+  const double LinearEdge::corner[2][3] = {  { -1, 0, 0 },
+                                         {  1, 0, 0 } };
 
+  LinearEdge::LinearEdge() : Map(0) {
+
+  }// LinearEdge::LinearEdge()
+
+  /* For each point, its weight and location are stored as an array.
+     Hence, the inner dimension is 2, the outer dimension is gauss_count.
+     We use a one-point Gaussian quadrature, since it integrates linear functions exactly.
+  */
+  const double LinearEdge::gauss[1][2] = { {  2.0,           0.0          } };
+
+  CartVect LinearEdge::evaluate( const CartVect& xi ) const {
+    CartVect x(0.0);
+    for (unsigned i = 0; i < LinearEdge::corner_count; ++i) {
+      const double N_i = (1.0 + xi[0]*corner[i][0]);
+      x += N_i * this->vertex[i];
+    }
+    x /= LinearEdge::corner_count;
+    return x;
+  }// LinearEdge::evaluate
+
+  Matrix3 LinearEdge::jacobian( const CartVect& xi ) const {
+    Matrix3 J(0.0);
+    for (unsigned i = 0; i < LinearEdge::corner_count; ++i) {
+      const double   xi_p = 1.0 + xi[0]*corner[i][0];
+      const double dNi_dxi   = corner[i][0] * xi_p ;
+      J(0,0) += dNi_dxi   * vertex[i][0];
+    }
+    J(1,1) = 1.0; /* to make sure the Jacobian determinant is non-zero */
+    J(2,2) = 1.0; /* to make sure the Jacobian determinant is non-zero */
+    J /= LinearEdge::corner_count;
+    return J;
+  }// LinearEdge::jacobian()
+
+  double LinearEdge::evaluate_scalar_field(const CartVect& xi, const double *field_vertex_value) const {
+    double f(0.0);
+    for (unsigned i = 0; i < LinearEdge::corner_count; ++i) {
+      const double N_i = (1 + xi[0]*corner[i][0])
+                          * (1.0 + xi[1]*corner[i][1]);
+      f += N_i * field_vertex_value[i];
+    }
+    f /= LinearEdge::corner_count;
+    return f;
+  }// LinearEdge::evaluate_scalar_field()
+
+  double LinearEdge::integrate_scalar_field(const double *field_vertex_values) const {
+    double I(0.0);
+    for(unsigned int j1 = 0; j1 < this->gauss_count; ++j1) {
+      double x1 = this->gauss[j1][1];
+      double w1 = this->gauss[j1][0];
+      CartVect x(x1,0.0,0.0);
+      I += this->evaluate_scalar_field(x,field_vertex_values)*w1*this->det_jacobian(x);
+    }
+    return I;
+  }// LinearEdge::integrate_scalar_field()
+
+  bool LinearEdge::inside_nat_space(const CartVect & xi, double & tol) const
+  {
+    // just look at the box+tol here
+    return ( xi[0]>=-1.-tol) && (xi[0]<=1.+tol) ;
+  }
 
 
   const double LinearHex::corner[8][3] = { { -1, -1, -1 },
@@ -487,7 +550,7 @@ namespace Element {
   CartVect LinearHex::evaluate( const CartVect& xi ) const {
     CartVect x(0.0);
     for (unsigned i = 0; i < 8; ++i) {
-      const double N_i = 
+      const double N_i =
         (1 + xi[0]*corner[i][0])
       * (1 + xi[1]*corner[i][1])
       * (1 + xi[2]*corner[i][2]);

diff --git a/tools/mbcoupler/ElemUtil.hpp b/tools/mbcoupler/ElemUtil.hpp
index a822621..60e7a76 100644
--- a/tools/mbcoupler/ElemUtil.hpp
+++ b/tools/mbcoupler/ElemUtil.hpp
@@ -248,11 +248,10 @@ namespace ElemUtil {
     };// class LinearQuad
 
     /**\brief Shape function space for bilinear quadrilateral, obtained from the canonical linear (affine) functions. */
-    class HOEdge : public Map {
+    class LinearEdge : public Map {
     public:
-      HOEdge(const std::vector<CartVect>& vertices) : Map(vertices){};
-      HOEdge();
-      virtual ~HOEdge();
+      LinearEdge(const std::vector<CartVect>& vertices) : Map(vertices){};
+      LinearEdge();
       virtual CartVect evaluate( const CartVect& xi ) const;
       //virtual CartVect ievaluate(const CartVect& x, double tol) const ;
       virtual bool inside_nat_space(const CartVect & xi, double & tol) const;
@@ -263,12 +262,12 @@ namespace ElemUtil {
 
     protected:
       /* Preimages of the vertices -- "canonical vertices" -- are known as "corners". */
-      static const double corner[4][3];
+      static const double corner[2][3];
       static const double gauss[1][2];
-      static const unsigned int corner_count = 4;
+      static const unsigned int corner_count = 2;
       static const unsigned int gauss_count  = 1;
 
-    };// class HOEdge
+    };// class LinearEdge
 
     class SpectralQuad : public Map {
       public:


https://bitbucket.org/fathomteam/moab/commits/bf609e1cc2c1/
Changeset:   bf609e1cc2c1
Branch:      None
User:        tautges
Date:        2013-04-30 22:00:35
Summary:     Some test additions.

Affected #:  2 files

diff --git a/test/elem_eval_test.cpp b/test/elem_eval_test.cpp
index f2a4d96..cd4c8a8 100644
--- a/test/elem_eval_test.cpp
+++ b/test/elem_eval_test.cpp
@@ -5,6 +5,7 @@
  *
  */
 #include "moab/Core.hpp"
+#include "moab/ReadUtilIface.hpp"
 #include "moab/ElemEvaluator.hpp"
 #include "moab/LinearHex.hpp"
 #include "moab/LinearTet.hpp"
@@ -39,12 +40,13 @@ CartVect hex_verts[] = {
     CartVect( 0, 0, 0 )
 };
 
+const double EPS1 = 1e-6;
+
 void test_eval(ElemEvaluator &ee, bool test_integrate) 
 {
   
   CartVect params, posn, params2;
   bool is_inside;
-  const double EPS1 = 1e-6;
   Matrix3 jacob;
   ErrorCode rval;
   
@@ -80,6 +82,25 @@ void test_eval(ElemEvaluator &ee, bool test_integrate)
   
 }
 
+void test_evals(ElemEvaluator &ee, bool test_integrate, EntityHandle *starth, int num_ents, double total_vol) 
+{
+  for (int i = 0; i < num_ents; i++)
+    test_eval(ee, false);
+    
+  if (!test_integrate) return;
+  if (!num_ents || !starth) CHECK_ERR(MB_FAILURE);
+
+  double tot_vol = 0.0;
+  EntityHandle eh = *starth;
+  for (int i = 0; i < num_ents; i++) {
+    double tmp_vol;
+    ee.set_ent_handle(eh++);
+    ErrorCode rval = ee.integrate(&tmp_vol); CHECK_ERR(rval);
+    tot_vol += tmp_vol;
+  }
+  CHECK_REAL_EQUAL(total_vol, tot_vol, EPS1);
+}
+
 int main()
 {
   int failures = 0;
@@ -128,16 +149,18 @@ void test_quadratic_hex()
 void test_linear_tet() 
 {
   Core mb;
-  Range verts;
-  ErrorCode rval = mb.create_vertices((double*)hex_verts[1].array(), 4, verts); CHECK_ERR(rval);
-  EntityHandle tet;
-  std::vector<EntityHandle> connect;
-  std::copy(verts.begin(), verts.end(), std::back_inserter(connect));
-  rval = mb.create_element(MBTET, connect.data(), 4, tet); CHECK_ERR(rval);
+  Range verts, tets;
+  ErrorCode rval = mb.create_vertices((double*)hex_verts[0].array(), 8, verts); CHECK_ERR(rval);
+  EntityHandle starth = 1, *conn;
+  int conn_inds[] = {1, 6, 4, 5,    1, 4, 6, 3,    0, 1, 3, 4,    1, 2, 3, 6,    3, 4, 6, 7};
+  ReadUtilIface *ru;
+  rval = mb.query_interface(ru); CHECK_ERR(rval);
+  rval = ru->get_element_connect(5, 4, MBTET, 1, starth, conn); CHECK_ERR(rval);
+  for (unsigned int i = 0; i < 20; i++) conn[i] = verts[conn_inds[i]];
   
-  ElemEvaluator ee(&mb, tet, 0);
+  ElemEvaluator ee(&mb, starth, 0);
   ee.set_tag_handle(0, 0);
   ee.set_eval_set(MBTET, LinearTet::eval_set());
 
-  test_eval(ee, false);
+  test_evals(ee, true, &starth, 5, 8.0);
 }

diff --git a/test/perf/point_location/elem_eval_time.cpp b/test/perf/point_location/elem_eval_time.cpp
index ea08956..186bd81 100644
--- a/test/perf/point_location/elem_eval_time.cpp
+++ b/test/perf/point_location/elem_eval_time.cpp
@@ -337,20 +337,19 @@ int main( int argc, char* argv[] )
             << " elements, " << nv << " vertices per element." << std::endl << std::endl;
   std::cout << "New, old element evaluation code:" << std::endl;
   std::cout << "Evaluation type, time, time per element:" << std::endl;
-  std::cout << "                New                   Old            (New-Old)/Old" << std::endl;
+  std::cout << "                             New                   Old            (New/Old)*100" << std::endl;
   std::cout << "Forward evaluation " << evtime[0] << ", " << evtime[0] / elems.size()
             << "    " << evtime[1] << ", " << evtime[1] / elems.size() 
-            << ", " << (evtime[0]-evtime[1])/(evtime[0]?evtime[0]:1) << std::endl;
+            << "    " << (evtime[0]/(evtime[1]?evtime[1]:1))*100.0 << std::endl;
   std::cout << "Reverse evaluation " << retime[0] << ", " << retime[0] / elems.size()
             << "    " << retime[1] << ", " << retime[1] / elems.size() 
-            << ", " << (retime[0]-retime[1])/(retime[0]?retime[0]:1) << std::endl;
+            << "    " << (retime[0]/(retime[1]?retime[1]:1))*100.0 << std::endl;
   std::cout << "Jacobian           " << jactime[0] << ", " << jactime[0] / elems.size()
             << "    " << jactime[1] << ", " << jactime[1] / elems.size() 
-            << ", " << (jactime[0]-jactime[1])/(jactime[0]?jactime[0]:1) << std::endl;
+            << "    " << (jactime[0]/(jactime[1]?jactime[1]:1))*100.0 << std::endl;
   std::cout << "Integration        " << inttime[0] << ", " << inttime[0] / elems.size()
             << "    " << inttime[1] << ", " << inttime[1] / elems.size() 
-            << ", " << (inttime[0]-inttime[1])/(inttime[0]?inttime[0]:1) << std::endl;
-  
+            << "    " << (inttime[0]/(inttime[1]?inttime[1]:1))*100.0 << std::endl;
 }
 
 #if defined(_MSC_VER) || defined(__MINGW32__)


https://bitbucket.org/fathomteam/moab/commits/3abdb67171b2/
Changeset:   3abdb67171b2
Branch:      None
User:        tautges
Date:        2013-04-30 22:07:01
Summary:     Merge branch 'master' of https://bitbucket.org/fathomteam/moab

Conflicts:
	.gitignore
	examples/old/KDTree.cpp
	src/parallel/TupleList.cpp
	src/parallel/moab/TupleList.hpp
	tools/mbcoupler/ElemUtil.cpp

Affected #:  96 files

diff --git a/Makefile.am b/Makefile.am
index 33a99cf..1c91622 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5,7 +5,7 @@ AUTOMAKE_OPTIONS = foreign
 ACLOCAL_AMFLAGS = -I config
 
 # Subdirectories to build
-SUBDIRS = src MeshFiles $(itaps_dir) tools test doc examples
+SUBDIRS = src MeshFiles $(itaps_dir) tools test doc
 
 if ENABLE_igeom
   itaps_dir_igeom = itaps

diff --git a/MeshFiles/unittest/disk.h5m b/MeshFiles/unittest/disk.h5m
new file mode 100644
index 0000000..ef19883
Binary files /dev/null and b/MeshFiles/unittest/disk.h5m differ

diff --git a/configure.ac b/configure.ac
index 562a8c8..b6fdaa9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1210,10 +1210,6 @@ AC_CONFIG_FILES([Makefile
                  doc/user.dox
                  doc/dev.dox
                  doc/config.tex
-                 examples/Makefile
-                 examples/examples.make
-                 examples/simple/makefile
-                 examples/itaps/Makefile
                  MeshFiles/Makefile
                  MeshFiles/unittest/Makefile
                  MeshFiles/unittest/io/Makefile

diff --git a/doc/user.dox.in b/doc/user.dox.in
index 703ce6b..4fed19e 100644
--- a/doc/user.dox.in
+++ b/doc/user.dox.in
@@ -52,7 +52,7 @@ EXTRACT_ALL            = YES
 # If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
 # will be included in the documentation.
 
-EXTRACT_PRIVATE        = NO
+EXTRACT_PRIVATE        = YES
 
 # If the EXTRACT_STATIC tag is set to YES all static members of a file 
 # will be included in the documentation.
@@ -112,7 +112,7 @@ STRIP_FROM_PATH        =
 # to NO (the default) then the documentation will be excluded. 
 # Set it to YES to include the internal documentation.
 
-INTERNAL_DOCS          = NO
+INTERNAL_DOCS          = YES
 
 # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
 # generate a class diagram (in Html and LaTeX) for classes with base or 
@@ -123,12 +123,12 @@ CLASS_DIAGRAMS         = YES
 # If the SOURCE_BROWSER tag is set to YES then a list of source files will 
 # be generated. Documented entities will be cross-referenced with these sources.
 
-SOURCE_BROWSER         = NO
+SOURCE_BROWSER         = YES
 
 # Setting the INLINE_SOURCES tag to YES will include the body 
 # of functions and classes directly in the documentation.
 
-INLINE_SOURCES         = NO
+INLINE_SOURCES         = YES
 
 # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
 # doxygen to hide any special comment blocks from generated source code 
@@ -199,12 +199,12 @@ SORT_MEMBER_DOCS       = YES
 # member in the group (if any) for the other members of the group. By default 
 # all members of a group must be documented explicitly.
 
-DISTRIBUTE_GROUP_DOC   = NO
+DISTRIBUTE_GROUP_DOC   = YES
 
 # The TAB_SIZE tag can be used to set the number of spaces in a tab. 
 # Doxygen uses this value to replace tabs by spaces in code fragments.
 
-TAB_SIZE               = 8
+TAB_SIZE               = 4
 
 # The GENERATE_TODOLIST tag can be used to enable (YES) or 
 # disable (NO) the todo list. This list is created by putting \todo 
@@ -304,14 +304,14 @@ WARN_LOGFILE           =
 # directories like "/usr/src/myproject". Separate the files or directories 
 # with spaces.
 
-INPUT                  = @top_srcdir@/src/moab \
+INPUT                  = @top_srcdir@/src @top_srcdir@/src/moab \
                          @top_srcdir@/src/parallel/moab \
                          @top_srcdir@/src/MBTagConventions.hpp \
                          @top_srcdir@/src/MBCN.h \
                          @top_srcdir@/src/MBEntityType.h \
                          @top_srcdir@/src/parallel/MBParallelConventions.h \
-                         @top_srcdir@/tools/dagmc/DagMC.hpp \
-                         @top_srcdir@/itaps @top_srcdir@/itaps/imesh
+                         @top_srcdir@/tools/ @top_srcdir@/tools/mbcoupler @top_srcdir@/tools/dagmc/DagMC.hpp \
+			 @top_srcdir@/itaps @top_srcdir@/itaps/imesh @top_srcdir@/examples
 
 # If the value of the INPUT tag contains directories, you can use the 
 # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
@@ -339,11 +339,11 @@ EXCLUDE                =
 
 EXCLUDE_PATTERNS       = 
 
-# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# The EXAMPLE_PATH tag can be used to specify one or more files or
 # directories that contain example code fragments that are included (see 
 # the \include command).
 
-EXAMPLE_PATH           =  
+EXAMPLE_PATH           =  @top_srcdir@/examples/
 
 # If the value of the EXAMPLE_PATH tag contains directories, you can use the 
 # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
@@ -458,7 +458,7 @@ BINARY_TOC             = NO
 # The TOC_EXPAND flag can be set to YES to add extra items for group members 
 # to the contents of the Html help documentation and to the tree view.
 
-TOC_EXPAND             = NO
+TOC_EXPAND             = YES
 
 # The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
 # top of each HTML page. The value NO (the default) enables the index and 
@@ -647,7 +647,7 @@ MACRO_EXPANSION        = NO
 # then the macro expansion is limited to the macros specified with the 
 # PREDEFINED and EXPAND_AS_PREDEFINED tags.
 
-EXPAND_ONLY_PREDEF     = NO
+EXPAND_ONLY_PREDEF     = YES
 
 # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
 # in the INCLUDE_PATH (see below) will be search if a #include is found.
@@ -808,7 +808,7 @@ DOT_CLEANUP            = YES
 # The SEARCHENGINE tag specifies whether or not a search engine should be 
 # used. If set to NO the values of all tags below this one will be ignored.
 
-SEARCHENGINE           = NO
+SEARCHENGINE           = YES
 
 # The CGI_NAME tag should be the name of the CGI script that 
 # starts the search engine (doxysearch) with the correct parameters. 

diff --git a/examples/A.1.ele b/examples/A.1.ele
deleted file mode 100644
index d742678..0000000
--- a/examples/A.1.ele
+++ /dev/null
@@ -1,31 +0,0 @@
-29  3  0
-   1      29     2     1
-   2       2    29    23
-   3      25    24    23
-   4      23    22     2
-   5      25    23    29
-   6       2    22     3
-   7       3    21     4
-   8      21     3    22
-   9       4    21    20
-  10       5     4    26
-  11      19    26     4
-  12      26    19    18
-  13      19     4    20
-  14       5    26    28
-  15      12    14    13
-  16      14    12    11
-  17      11    10     9
-  18       8    14     9
-  19       8    15    14
-  20       9    14    11
-  21       6    27     7
-  22      26    18    27
-  23       5    28     6
-  24      27    18     7
-  25      28    27     6
-  26      15     7    16
-  27       7    15     8
-  28      17     7    18
-  29       7    17    16
-# Generated by triangle A.poly

diff --git a/examples/A.1.node b/examples/A.1.node
deleted file mode 100644
index 31d09f1..0000000
--- a/examples/A.1.node
+++ /dev/null
@@ -1,31 +0,0 @@
-29  2  1  1
-   1    0.20000000000000001  -0.77639999999999998  -0.56999999999999995    1
-   2    0.22  -0.7732  -0.55000000000000004    1
-   3    0.24560000000000001  -0.75639999999999996  -0.51000000000000001    1
-   4    0.27760000000000001  -0.70199999999999996  -0.53000000000000003    1
-   5    0.48880000000000001  -0.20760000000000001  0.28000000000000003    1
-   6    0.50480000000000003  -0.20760000000000001  0.29999999999999999    1
-   7    0.74080000000000001  -0.73960000000000004  0    1
-   8    0.75600000000000001  -0.76119999999999999  -0.01    1
-   9    0.77439999999999998  -0.77239999999999998  0    1
-  10    0.80000000000000004  -0.77639999999999998  0.02    1
-  11    0.80000000000000004  -0.79239999999999999  0.01    1
-  12    0.57920000000000005  -0.79239999999999999  -0.20999999999999999    1
-  13    0.57920000000000005  -0.77639999999999998  -0.20000000000000001    1
-  14    0.62160000000000004  -0.77159999999999995  -0.14999999999999999    1
-  15    0.63360000000000005  -0.76280000000000003  -0.13    1
-  16    0.63919999999999999  -0.74439999999999995  -0.10000000000000001    1
-  17    0.62080000000000002  -0.68440000000000001  -0.059999999999999998    1
-  18    0.58720000000000006  -0.60440000000000005  -0.01    1
-  19    0.36080000000000001  -0.60440000000000005  -0.23999999999999999    1
-  20    0.31919999999999998  -0.70679999999999998  -0.39000000000000001    1
-  21    0.312  -0.73960000000000004  -0.42999999999999999    1
-  22    0.31840000000000002  -0.76119999999999999  -0.44    1
-  23    0.33439999999999998  -0.77159999999999995  -0.44    1
-  24    0.37119999999999997  -0.77639999999999998  -0.40999999999999998    1
-  25    0.37119999999999997  -0.79239999999999999  -0.41999999999999998    1
-  26    0.37440000000000001  -0.56999999999999995  -0.20000000000000001    1
-  27    0.57440000000000002  -0.56999999999999995  0    1
-  28    0.47360000000000002  -0.33079999999999998  0.14000000000000001    1
-  29    0.20000000000000001  -0.79239999999999999  -0.58999999999999997    1
-# Generated by triangle A.poly

diff --git a/examples/DirectAccessNoHoles.cpp b/examples/DirectAccessNoHoles.cpp
new file mode 100644
index 0000000..445c517
--- /dev/null
+++ b/examples/DirectAccessNoHoles.cpp
@@ -0,0 +1,179 @@
+/** @example DirectAccess.cpp \n
+ * \brief Use direct access to MOAB data to avoid calling through API \n
+ *
+ * This example creates a 1d row of quad elements, with a user-specified number of "holes" (missing quads) in the row:
+ *
+ *  ----------------------      ----------------------      --------
+ *  |      |      |      |      |      |      |      |      |      |       
+ *  |      |      |      |(hole)|      |      |      |(hole)|      | ...
+ *  |      |      |      |      |      |      |      |      |      |
+ *  ----------------------      ----------------------      --------
+ *
+ * This makes (nholes+1) contiguous runs of quad handles in the handle space
+ * This example shows how to use the xxx_iterate functions in MOAB (xxx = coords, connect, tag, adjacencies) to get 
+ * direct pointer access to MOAB internal storage, which can be used without calling through the MOAB API.
+ *
+ *    -#  Initialize MOAB \n
+ *    -#  Create a quad mesh with holes, as depicted above
+ *    -#  Create 2 dense tags (tag1, tag2) for avg position to assign to quads, and # verts per quad (tag3)
+ *    -#  Get connectivity, coordinate, tag1 iterators
+ *    -#  Iterate through quads, computing midpoint based on vertex positions, set on quad-based tag1
+ *    -#  Set up map from starting quad handle for a chunk to struct of (tag1_ptr, tag2_ptr, tag3_ptr), pointers to
+ *        the dense tag storage for those tags for the chunk
+ *    -#  Iterate through vertices, summing positions into tag2 on connected quads and incrementing vertex count
+ *    -#  Iterate through quads, normalizing tag2 by vertex count and comparing values of tag1 and tag2
+ *
+ * <b>To compile</b>: \n
+ *    make DirectAccessWithHoles MOAB_DIR=<installdir>  \n
+ * <b>To run</b>: ./DirectAccess [-nquads <# quads>] [-holes <# holes>]\n
+ *
+ */
+
+#include "moab/Core.hpp"
+#include "moab/ProgOptions.hpp"
+#include "moab/ReadUtilIface.hpp"
+#include <map>
+#include <iostream>
+#include <assert.h>
+
+// Error routines for use with MOAB API
+#define CHKERR(CODE, MSG) do {if (MB_SUCCESS != (CODE)) {std::string errstr;  mbImpl->get_last_error(errstr);   \
+        std::cerr << errstr << std::endl; std::cerr << MSG << std::endl; return CODE;}} while(false)
+
+using namespace moab;
+
+ErrorCode create_mesh_no_holes(Interface *mbImpl, int nquads);
+
+int main(int argc, char **argv)
+{
+    // get MOAB instance
+  Interface *mbImpl = new Core;
+  if (NULL == mbImpl) return 1;
+
+  int nquads = 1000;
+  
+    // parse options
+  ProgOptions opts;
+  opts.addOpt<int>(std::string("nquads,n"), std::string("Number of quads in the mesh (default = 1000"), &nquads);
+  opts.parseCommandLine(argc, argv);
+
+    // create simple structured mesh with hole, but using unstructured representation
+  ErrorCode rval = create_mesh_no_holes(mbImpl, nquads); CHKERR(rval, "Trouble creating mesh.");
+  
+    // get all vertices and non-vertex entities
+  Range verts, quads;
+  rval = mbImpl->get_entities_by_handle(0, quads); CHKERR(rval, "Getting all entities.");
+  verts = quads.subset_by_dimension(0);
+  quads -= verts;
+
+    // create tag1 (element-based avg), tag2 (vertex-based avg), tag3 (# connected verts)
+  Tag tag1, tag2, tag3;
+  rval = mbImpl->tag_get_handle("tag1", 3, MB_TYPE_DOUBLE, tag1, MB_TAG_DENSE | MB_TAG_CREAT); CHKERR(rval, "Creating tag1.");
+  double def_val[3] = {0.0, 0.0, 0.0}; // need a default value for tag2 because we sum into it
+  rval = mbImpl->tag_get_handle("tag2", 3, MB_TYPE_DOUBLE, tag2, MB_TAG_DENSE | MB_TAG_CREAT, def_val); CHKERR(rval, "Creating tag2.");
+  int def_val_int = 0;  // need a default value for tag3 because we increment it
+  rval = mbImpl->tag_get_handle("tag3", 1, MB_TYPE_INTEGER, tag3, MB_TAG_DENSE | MB_TAG_CREAT, &def_val_int); CHKERR(rval, "Creating tag3.");
+  
+    // Get pointers to connectivity, coordinate, tag, and adjacency arrays; each of these returns a count,
+    // which should be compared to the # entities you expect to verify there's only one chunk (no holes)
+  int count, vpere;
+  EntityHandle *conn_ptr;
+  rval = mbImpl->connect_iterate(quads.begin(), quads.end(), conn_ptr, vpere, count); CHKERR(rval, "connect_iterate.");
+  assert(count == (int) quads.size()); // should end up with just one contiguous chunk of quads
+
+  double *x_ptr, *y_ptr, *z_ptr;
+  rval = mbImpl->coords_iterate(verts.begin(), verts.end(), x_ptr, y_ptr, z_ptr, count); CHKERR(rval, "coords_iterate.");
+  assert(count == (int) verts.size()); // should end up with just one contiguous chunk of vertices
+
+  double *tag1_ptr, *tag2_ptr;
+  int *tag3_ptr;
+  rval = mbImpl->tag_iterate(tag1, quads.begin(), quads.end(), count, (void*&)tag1_ptr); CHKERR(rval, "tag1_iterate.");
+  assert(count == (int) quads.size()); // should end up with just one contiguous chunk of quads
+  rval = mbImpl->tag_iterate(tag2, quads.begin(), quads.end(), count, (void*&)tag2_ptr); CHKERR(rval, "tag2_iterate.");
+  assert(count == (int) quads.size()); // should end up with just one contiguous chunk of quads
+  rval = mbImpl->tag_iterate(tag3, quads.begin(), quads.end(), count, (void*&)tag3_ptr); CHKERR(rval, "tag3_iterate.");
+  assert(count == (int) quads.size()); // should end up with just one contiguous chunk of quads
+
+  const std::vector<EntityHandle> **adjs_ptr;
+  rval = mbImpl->adjacencies_iterate(verts.begin(), verts.end(), adjs_ptr, count); CHKERR(rval, "adjacencies_iterate.");
+  assert(count == (int) verts.size()); // should end up with just one contiguous chunk of vertices
+  
+    // Start_ handles used to compute indices into vertex/quad arrays; can use direct subtraction because we know
+    // there aren't any holes in the handle spaces for verts or quads
+  EntityHandle start_vert = *verts.begin(), start_quad = *quads.begin();
+
+    // iterate over elements, computing tag1 from coords positions
+  for (int i = 0; i < nquads; i++) {
+    tag1_ptr[3*i+0] = tag1_ptr[3*i+1] = tag1_ptr[3*i+2] = 0.0; // initialize position for this element
+    for (int j = 0; j < vpere; j++) { // loop over vertices in this element
+      int v_index = conn_ptr[vpere*i+j] - start_vert; // vert index is just the offset from start vertex
+      tag1_ptr[3*i+0] += x_ptr[v_index];
+      tag1_ptr[3*i+1] += y_ptr[v_index]; // sum vertex positions into tag1...
+      tag1_ptr[3*i+2] += z_ptr[v_index];
+    }
+    tag1_ptr[3*i+0] /= vpere;
+    tag1_ptr[3*i+1] /= vpere; // then normalize
+    tag1_ptr[3*i+2] /= vpere;
+  } // loop over elements in chunk
+    
+    // Iterate through vertices, summing positions into tag2 on connected elements and incrementing vertex count
+  for (int v = 0; v < count; v++) {
+    const std::vector<EntityHandle> *avec = *(adjs_ptr+v);
+    for (std::vector<EntityHandle>::const_iterator ait = avec->begin(); ait != avec->end(); ait++) {
+        // *ait is the quad handle, its index is computed by subtracting the start quad handle
+      int a_ind = *ait - start_quad;
+      tag2_ptr[3*a_ind+0] += x_ptr[v];   // tag on each element is 3 doubles, x/y/z
+      tag2_ptr[3*a_ind+1] += y_ptr[v];
+      tag2_ptr[3*a_ind+2] += z_ptr[v];
+      tag3_ptr[a_ind]++;  // increment the vertex count
+    }
+  }
+        
+    // Normalize tag2 by vertex count (tag3); loop over elements using same approach as before
+    // At the same time, compare values of tag1 and tag2
+  for (Range::iterator q_it = quads.begin(); q_it != quads.end(); q_it++) {
+    int i = *q_it - start_quad;
+    for (int j = 0; j < 3; j++) tag2_ptr[3*i+j] /= (double)tag3_ptr[i];  // normalize by # verts
+    if (tag1_ptr[3*i] != tag2_ptr[3*i] || tag1_ptr[3*i+1] != tag2_ptr[3*i+1] || tag1_ptr[3*i+2] != tag2_ptr[3*i+2]) 
+      std::cout << "Tag1, tag2 disagree for element " << *q_it + i << std::endl;
+  }
+
+    // Ok, we're done, shut down MOAB
+  delete mbImpl;
+
+  return 0;
+}
+
+ErrorCode create_mesh_no_holes(Interface *mbImpl, int nquads) 
+{
+    // first make the mesh, a 1d array of quads with left hand side x = elem_num; vertices are numbered in layers
+  ReadUtilIface *read_iface;
+  ErrorCode rval = mbImpl->query_interface(read_iface); CHKERR(rval, "query_interface");
+  std::vector<double *> coords;
+  EntityHandle start_vert, start_elem, *connect;
+    // create verts, num is 4(nquads+1) because they're in a 1d row; will initialize coords in loop over quads later
+  rval = read_iface->get_node_coords (3, 2*(nquads+1), 0, start_vert, coords); CHKERR(rval, "get_node_arrays");
+    // create quads
+  rval = read_iface->get_element_connect(nquads, 4, MBQUAD, 0, start_elem, connect); CHKERR(rval, "get_element_connect");
+  for (int i = 0; i < nquads; i++) {
+    coords[0][2*i] = coords[0][2*i+1] = (double) i; // x values are all i
+    coords[1][2*i] = 0.0; coords[1][2*i+1] = 1.0; // y coords
+    coords[2][2*i] = coords[2][2*i+1] = (double) 0.0; // z values, all zero (2d mesh)
+    EntityHandle quad_v = start_vert + 2*i;
+    for (int j = 0; j < 4; j++) connect[4*i+j] = quad_v+j; // connectivity of each quad is a sequence starting from quad_v
+  }
+    // last two vertices
+  coords[0][2*nquads] = coords[0][2*nquads+1] = (double) nquads;
+  coords[1][2*nquads] = 0.0; coords[1][2*nquads+1] = 1.0; // y coords
+  coords[2][2*nquads] = coords[2][2*nquads+1] = (double) 0.0; // z values, all zero (2d mesh)
+  
+    // call a vertex-quad adjacencies function to generate vertex-element adjacencies in MOAB
+  Range dum_range;
+  rval = mbImpl->get_adjacencies(&start_vert, 1, 2, false, dum_range); CHKERR(rval, "get_adjacencies");
+  assert(!dum_range.empty());
+
+  return MB_SUCCESS;
+}
+
+    
+  

diff --git a/examples/DirectAccessWithHoles.cpp b/examples/DirectAccessWithHoles.cpp
new file mode 100644
index 0000000..524c30f
--- /dev/null
+++ b/examples/DirectAccessWithHoles.cpp
@@ -0,0 +1,239 @@
+/** @example DirectAccess.cpp \n
+ * \brief Use direct access to MOAB data to avoid calling through API \n
+ *
+ * This example creates a 1d row of quad elements, with a user-specified number of "holes" (missing quads) in the row:
+ *
+ *  ----------------------      ----------------------      --------
+ *  |      |      |      |      |      |      |      |      |      |       
+ *  |      |      |      |(hole)|      |      |      |(hole)|      | ...
+ *  |      |      |      |      |      |      |      |      |      |
+ *  ----------------------      ----------------------      --------
+ *
+ * This makes (nholes+1) contiguous runs of quad handles in the handle space
+ * This example shows how to use the xxx_iterate functions in MOAB (xxx = coords, connect, tag, adjacencies) to get 
+ * direct pointer access to MOAB internal storage, which can be used without calling through the MOAB API.
+ *
+ *    -#  Initialize MOAB \n
+ *    -#  Create a quad mesh with holes, as depicted above
+ *    -#  Create 2 dense tags (tag1, tag2) for avg position to assign to quads, and # verts per quad (tag3)
+ *    -#  Get connectivity, coordinate, tag1 iterators
+ *    -#  Iterate through quads, computing midpoint based on vertex positions, set on quad-based tag1
+ *    -#  Set up map from starting quad handle for a chunk to struct of (tag1_ptr, tag2_ptr, tag3_ptr), pointers to
+ *        the dense tag storage for those tags for the chunk
+ *    -#  Iterate through vertices, summing positions into tag2 on connected quads and incrementing vertex count
+ *    -#  Iterate through quads, normalizing tag2 by vertex count and comparing values of tag1 and tag2
+ *
+ * <b>To compile</b>: \n
+ *    make DirectAccessWithHoles MOAB_DIR=<installdir>  \n
+ * <b>To run</b>: ./DirectAccess [-nquads <# quads>] [-holes <# holes>]\n
+ *
+ */
+
+#include "moab/Core.hpp"
+#include "moab/ProgOptions.hpp"
+#include "moab/ReadUtilIface.hpp"
+#include <map>
+#include <iostream>
+#include <assert.h>
+
+// Error routines for use with MOAB API
+#define CHKERR(CODE, MSG) do {if (MB_SUCCESS != (CODE)) {std::string errstr;  mbImpl->get_last_error(errstr);   \
+        std::cerr << errstr << std::endl; std::cerr << MSG << std::endl; return CODE;}} while(false)
+
+using namespace moab;
+
+ErrorCode create_mesh_with_holes(Interface *mbImpl, int nquads, int nholes);
+
+struct tag_struct {double *avg_ptr; int *nv_ptr;};
+
+int main(int argc, char **argv)
+{
+    // get MOAB instance
+  Interface *mbImpl = new Core;
+  if (NULL == mbImpl) return 1;
+
+  int nquads = 1000, nholes = 1;
+  
+    // parse options
+  ProgOptions opts;
+  opts.addOpt<int>(std::string("nquads,n"), std::string("Number of quads in the mesh (default = 1000"), &nquads);
+  opts.addOpt<int>(std::string("holes,H"), std::string("Number of holes in the element handle space (default = 1"), &nholes);
+  opts.parseCommandLine(argc, argv);
+  if (nholes >= nquads) {
+    std::cerr << "Number of holes needs to be < number of elements." << std::endl;
+    return 1;
+  }
+
+    // create simple structured mesh with hole, but using unstructured representation
+  ErrorCode rval = create_mesh_with_holes(mbImpl, nquads, nholes); CHKERR(rval, "Trouble creating mesh.");
+  
+    // get all vertices and non-vertex entities
+  Range verts, elems;
+  rval = mbImpl->get_entities_by_handle(0, elems); CHKERR(rval, "Getting all entities.");
+  verts = elems.subset_by_dimension(0);
+  elems -= verts;
+
+    // create tag1 (element-based avg), tag2 (vertex-based avg), tag3 (# connected verts)
+  Tag tag1, tag2, tag3;
+  rval = mbImpl->tag_get_handle("tag1", 3, MB_TYPE_DOUBLE, tag1, MB_TAG_DENSE | MB_TAG_CREAT); CHKERR(rval, "Creating tag1.");
+  double def_val[3] = {0.0, 0.0, 0.0}; // need a default value for tag2 because we sum into it
+  rval = mbImpl->tag_get_handle("tag2", 3, MB_TYPE_DOUBLE, tag2, MB_TAG_DENSE | MB_TAG_CREAT, def_val); CHKERR(rval, "Creating tag2.");
+  int def_val_int = 0;  // need a default value for tag3 because we increment it
+  rval = mbImpl->tag_get_handle("tag3", 1, MB_TYPE_INTEGER, tag3, MB_TAG_DENSE | MB_TAG_CREAT, &def_val_int); CHKERR(rval, "Creating tag3.");
+  
+    // Get connectivity, coordinate, tag, and adjacency iterators
+  EntityHandle *conn_ptr;
+  double *x_ptr, *y_ptr, *z_ptr, *tag1_ptr, *tag2_ptr;
+  int *tag3_ptr;
+  
+    // First vertex is at start of range (ranges are sorted), and is offset for vertex index calculation
+  EntityHandle first_vert = *verts.begin();
+
+    // When iterating over elements, each chunk can have a different # vertices; also, count tells you how many
+    // elements are in the current chunk
+  int vpere, count;
+  
+    // Get coordinates iterator, just need this once because we know verts handle space doesn't have holes
+  rval = mbImpl->coords_iterate(verts.begin(), verts.end(), x_ptr, y_ptr, z_ptr, count); CHKERR(rval, "coords_iterate.");
+  assert(count == (int) verts.size()); // should end up with just one contiguous chunk of vertices
+
+    // Iterate through elements, computing midpoint based on vertex positions, set on element-based tag1
+    // Control loop by iterator over elem range
+  Range::iterator e_it = elems.begin();
+
+  while (e_it != elems.end()) {
+      // get conn_ptr, tag1_ptr for next contiguous chunk of element handles, and coords pointers for all verts
+    rval = mbImpl->connect_iterate(e_it, elems.end(), conn_ptr, vpere, count); CHKERR(rval, "connect_iterate.");
+    rval = mbImpl->tag_iterate(tag1, e_it, elems.end(), count, (void*&)tag1_ptr); CHKERR(rval, "tag1_iterate.");
+
+      // iterate over elements in this chunk 
+    for (int i = 0; i < count; i++) {
+      tag1_ptr[0] = tag1_ptr[1] = tag1_ptr[2] = 0.0; // initialize position for this element
+      for (int j = 0; j < vpere; j++) { // loop over vertices in this element
+        int v_index = conn_ptr[j] - first_vert; // vert index is just the offset from first vertex
+        tag1_ptr[0] += x_ptr[v_index];
+        tag1_ptr[1] += y_ptr[v_index]; // sum vertex positions into tag1...
+        tag1_ptr[2] += z_ptr[v_index];
+      }
+      tag1_ptr[0] /= vpere;
+      tag1_ptr[1] /= vpere; // then normalize
+      tag1_ptr[2] /= vpere;
+      
+        // done with this element; advance connect_ptr and tag1_ptr to next element
+      conn_ptr += vpere;
+      tag1_ptr += 3;
+    } // loop over elements in chunk
+    
+      // done with chunk; advance range iterator by count; will skip over gaps in range
+    e_it += count;
+  } // while loop over all elements
+  
+    // Iterate through vertices, summing positions into tag2 on connected elements and incrementing vertex count
+    // Iterate over chunks the same as elements, even though we know we have only one chunk here, just to show
+    // how it's done
+
+    // Create a std::map from EntityHandle (first entity handle in chunk) to 
+    // tag_struct (ptrs to start of avg/#verts tags for that chunk); then for a given entity handle, we can quickly
+    // find the chunk it's in using map::lower_bound; could have set up this map in earlier loop over elements, but do
+    // it here for clarity
+  
+  std::map< EntityHandle, tag_struct> elem_map;
+  e_it = elems.begin();
+  while (e_it != elems.end()) {
+    tag_struct ts = {NULL, NULL};
+    rval = mbImpl->tag_iterate(tag2, e_it, elems.end(), count, (void*&)ts.avg_ptr); CHKERR(rval, "tag2_iterate.");
+    rval = mbImpl->tag_iterate(tag3, e_it, elems.end(), count, (void*&)ts.nv_ptr); CHKERR(rval, "tag3_iterate.");
+    elem_map[*e_it] = ts;
+    e_it += count;
+  }
+
+    // call a vertex-quad adjacencies function to generate vertex-element adjacencies in MOAB
+  Range::iterator v_it = verts.begin();
+  Range dum_range;
+  rval = mbImpl->get_adjacencies(&(*v_it), 1, 2, false, dum_range); CHKERR(rval, "get_adjacencies");
+  const std::vector<EntityHandle> **adjs_ptr;
+  while (v_it != verts.end()) {
+      // get coords ptrs, adjs_ptr; can't set tag2_ptr by direct access, because of hole in element handle space
+    rval = mbImpl->coords_iterate(v_it, verts.end(), x_ptr, y_ptr, z_ptr, count); CHKERR(rval, "coords_iterate.");
+    rval = mbImpl->adjacencies_iterate(v_it, verts.end(), adjs_ptr, count); CHKERR(rval, "adjacencies_iterate.");
+    
+    for (int v = 0; v < count; v++) {
+      const std::vector<EntityHandle> *avec = *(adjs_ptr+v);
+      for (std::vector<EntityHandle>::const_iterator ait = avec->begin(); ait != avec->end(); ait++) {
+          // get chunk that this element resides in; upper_bound points to the first element strictly > key, so get that and decrement
+          // (would work the same as lower_bound with an if-test and decrement)
+        std::map<EntityHandle, tag_struct>::iterator mit = elem_map.upper_bound(*ait); mit--;
+          // index of *ait in that chunk
+        int a_ind = *ait - (*mit).first;
+        tag_struct ts = (*mit).second;
+        ts.avg_ptr[3*a_ind]   += x_ptr[v];   // tag on each element is 3 doubles, x/y/z
+        ts.avg_ptr[3*a_ind+1] += y_ptr[v];
+        ts.avg_ptr[3*a_ind+2] += z_ptr[v];
+        ts.nv_ptr[a_ind]++;  // increment the vertex count
+      }
+    }
+
+    v_it += count;
+  }
+        
+    // Normalize tag2 by vertex count; loop over elements using same approach as before
+    // At the same time, compare values of tag1 and tag2
+  e_it = elems.begin();
+  while (e_it != elems.end()) {
+      // get conn_ptr, tag1_ptr for next contiguous chunk of element handles, and coords pointers for all verts
+    rval = mbImpl->tag_iterate(tag1, e_it, elems.end(), count, (void*&)tag1_ptr); CHKERR(rval, "tag1_iterate.");
+    rval = mbImpl->tag_iterate(tag2, e_it, elems.end(), count, (void*&)tag2_ptr); CHKERR(rval, "tag2_iterate.");
+    rval = mbImpl->tag_iterate(tag3, e_it, elems.end(), count, (void*&)tag3_ptr); CHKERR(rval, "tag3_iterate.");
+
+      // iterate over elements in this chunk 
+    for (int i = 0; i < count; i++) {
+      for (int j = 0; j < 3; j++) tag2_ptr[3*i+j] /= (double)tag3_ptr[i];  // normalize by # verts
+      if (tag1_ptr[3*i] != tag2_ptr[3*i] || tag1_ptr[3*i+1] != tag2_ptr[3*i+1] || tag1_ptr[3*i+2] != tag2_ptr[3*i+2]) 
+        std::cout << "Tag1, tag2 disagree for element " << *e_it + i << std::endl;
+    }
+
+    e_it += count;
+  }
+
+    // Ok, we're done, shut down MOAB
+  delete mbImpl;
+
+  return 0;
+}
+
+ErrorCode create_mesh_with_holes(Interface *mbImpl, int nquads, int nholes) 
+{
+    // first make the mesh, a 1d array of quads with left hand side x = elem_num; vertices are numbered in layers
+  ReadUtilIface *read_iface;
+  ErrorCode rval = mbImpl->query_interface(read_iface); CHKERR(rval, "query_interface");
+  std::vector<double *> coords;
+  EntityHandle start_vert, start_elem, *connect;
+    // create verts, num is 4(nquads+1) because they're in a 1d row; will initialize coords in loop over elems later
+  rval = read_iface->get_node_coords (3, 2*(nquads+1), 0, start_vert, coords); CHKERR(rval, "get_node_arrays");
+    // create elems
+  rval = read_iface->get_element_connect(nquads, 4, MBQUAD, 0, start_elem, connect); CHKERR(rval, "get_element_connect");
+  for (int i = 0; i < nquads; i++) {
+    coords[0][2*i] = coords[0][2*i+1] = (double) i; // x values are all i
+    coords[1][2*i] = 0.0; coords[1][2*i+1] = 1.0; // y coords
+    coords[2][2*i] = coords[2][2*i+1] = (double) 0.0; // z values, all zero (2d mesh)
+    EntityHandle quad_v = start_vert + 2*i;
+    for (int j = 0; j < 4; j++) connect[4*i+j] = quad_v+j; // connectivity of each quad is a sequence starting from quad_v
+  }
+    // last two vertices
+  coords[0][2*nquads] = coords[0][2*nquads+1] = (double) nquads;
+  coords[1][2*nquads] = 0.0; coords[1][2*nquads+1] = 1.0; // y coords
+  coords[2][2*nquads] = coords[2][2*nquads+1] = (double) 0.0; // z values, all zero (2d mesh)
+  
+    // now delete nholes elements, spaced approximately equally through mesh, so contiguous size is about nquads/(nholes+1)
+    // reinterpret start_elem as the next element to be deleted
+  int de = nquads / (nholes + 1);
+  for (int i = 0; i < nholes; i++) {
+    start_elem += de;
+    rval = mbImpl->delete_entities(&start_elem, 1); CHKERR(rval, "delete_entities");
+  }
+  
+  return MB_SUCCESS;
+}
+
+    
+  

diff --git a/examples/FileRead.cpp b/examples/FileRead.cpp
deleted file mode 100644
index bff9e28..0000000
--- a/examples/FileRead.cpp
+++ /dev/null
@@ -1,164 +0,0 @@
-#include <iostream>
-#include <fstream>
-#include <vector>
-#include <string>
-#include <sstream> 
-
-#include "moab/Core.hpp"
-#include "moab/ReadUtilIface.hpp"
-
-using namespace std;
-using namespace moab;
-
-int comment(string & line)
-{
-    // if a line starts with '#' is a comment
-    // eat white space characters
-    size_t found=line.find_first_not_of(" \t");
-    if (found==string::npos)
-	return 1; // empty line
-    if ('#'==line[found])
-        return 1; // a comment indeed
-    return 0; // a line with some data in it, then
-
-}
-ErrorCode ReadTriangleOutput( Interface *mb, string fileBase ) {    
-  
-  //
-  // get the read interface from moab
-  ReadUtilIface *iface;
-  ErrorCode rval = mb->query_interface(iface);
-  //
-  if (MB_SUCCESS != rval)
-     {
-        cout<<"Can't get interface.\n";
-        return MB_FAILURE;
-     }
-  // Triangle default <name>.node
-  string nodeFileName = fileBase+".node";
-  ifstream nodeFile (nodeFileName.c_str());
-  if (!nodeFile.is_open())
-  {
-     cout<<"can't open node file .\n";
-     return MB_FILE_DOES_NOT_EXIST;
-  }
-  cout << "reading nodes from file " << nodeFileName.c_str() << endl;
-  
-  string eleFileName = fileBase+".ele";
-  ifstream eleFile (eleFileName.c_str());
-  if (!eleFile.is_open())
-  {
-     cout<<"can't open element file .\n";
-     return MB_FILE_DOES_NOT_EXIST;
-  }
-  cout << "reading elements from file " << eleFileName.c_str() << endl;
-
-  string line;
-  
-  // ignore comment lines that start with #
-  
-  int num_nodes=0, num_triangles=0;
-  while(num_nodes==0)
-    {
-      getline(nodeFile, line);
-      if (comment(line))
-	continue;
-      stringstream tks(line);
-      tks >> num_nodes; // ignore the rest of the first line
-                        // maybe will read attributes some other time
-      cout << "num nodes:" << num_nodes << endl; 
-    }
-  
-  //  allocate a block of vertex handles and read xyz’s into them
-  //  we know the size of the node arrays, and this call will allocate 
-  //   needed arrays, coordinate arrays
-  //   also, it will return a starting handle for the node sequence
-  vector<double*> arrays;
-  EntityHandle startv;
-  rval = iface->get_node_coords(2, num_nodes, 0, startv, arrays);
-  for (int i = 0; i < num_nodes; i++)
-    {
-      getline(nodeFile, line);
-      if (comment(line))
-      {
-        i--;// read one more line
-	continue;
-      }
-      stringstream tokens(line);
-      int nodeId;
-      tokens >> nodeId >> arrays[0][i] >> arrays[1][i] ;
-    }
-  
-  // now read the element data from a different file
-  // first, find out how many elements are out there
-  // first line with data should have it
-  while(num_triangles==0)
-    {
-      getline(eleFile, line);
-      if (comment(line))
-	continue;
-      stringstream tks(line);
-      tks >> num_triangles; // ignore the rest of the line
-      cout << "num triangles:" << num_triangles << endl; 
-    }
-
-  EntityHandle starte;
-  EntityHandle *starth; // the connectivity array that will get populated
-                          // with triangle data
-  // allocate block of triangle handles and read connectivity into them
-  rval = iface->get_element_connect(num_triangles, 3, MBTRI, 0, starte, starth);
-  
-  for (int j = 0; j < num_triangles; j++)
-    {
-      getline(eleFile, line);
-      if (comment(line))
-      {
-        j--;// read one more line
-	continue;
-      }
-      stringstream tokens(line);
-      int eleId;
-      unsigned int node;
-      tokens >> eleId;
-      for (int k=0; k<3; k++)
-	{
-	  tokens >> node;
-          // vertex handles start at startv
-            starth[3*j+k] = startv + node - 1;
-        }
-    }
-
-  mb->release_interface(iface);
-  //       
-  return MB_SUCCESS;
-}
-
-
-// .
-//  Read Triangle output files 
-//  Assume that the format is <filename>.node and <filename>.ele
-//   see  http://www.cs.cmu.edu/~quake/triangle.html for details
-//
-int main(int argc, char **argv) {
-  if (3!=argc) {
-    cout << "Usage: " << argv[0] << " <filename><outFile> " << endl;
-    cout << "       <filename>  is the base file name; *.ele and *.node file are read; outFile is a file with an extension recognized by MOAB " << endl;
-    return 0;
-  }     
-
-  string filename = argv[1];
-  char * outfile = argv[2];
-  
-
-  // get MOAB instance and read the file                                                                                                  
-  Core *mb = new Core();
-
-   ErrorCode rval = ReadTriangleOutput(mb, filename);
-
-   if (rval==MB_SUCCESS)
-   {
-     cout << "Writing output file " << outfile << endl;
-     mb->write_file(outfile); 
-   }
-   return 0;
-}  

diff --git a/examples/GeomSetHierarchy.cpp b/examples/GeomSetHierarchy.cpp
deleted file mode 100644
index a49dafe..0000000
--- a/examples/GeomSetHierarchy.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-#include "moab/Core.hpp"
-#include "moab/Range.hpp"
-#include "MBCN.hpp"
-#include "MBTagConventions.hpp"
-#include "moab/GeomTopoTool.hpp"
-#include <iostream>
-
-const char *ent_names[] = {"Vertex", "Edge", "Face", "Region"};
-
-int main(int argc, char **argv) {
-  if (1 == argc) {
-    std::cout << "Usage: " << argv[0] << " <filename>" << std::endl;
-    return 0;
-  }
-  
-    // instantiate & load a file
-  moab::Interface *mb = new moab::Core();
-  moab::ErrorCode rval = mb->load_file(argv[1]);
-
-    // get the geometric topology tag handle
-  moab::Tag geom_tag, gid_tag;
-  rval = mb->tag_get_handle(GEOM_DIMENSION_TAG_NAME, 1, moab::MB_TYPE_INTEGER, geom_tag);
-  rval = mb->tag_get_handle(GLOBAL_ID_TAG_NAME, 1, moab::MB_TYPE_INTEGER, gid_tag);
-
-    // traverse the model, from dimension 3 downward
-  moab::Range psets, chsets;
-  std::vector<moab::EntityHandle> sense_ents;
-  std::vector<int> senses, pgids;
-  int dim, pgid, chgid;
-  void *dim_ptr = &dim;
-  int sense;
-
-  moab::GeomTopoTool gt(mb, true);
-  
-  for (dim = 3; dim >= 0; dim--) {
-      // get parents at this dimension
-    chsets.clear();
-    rval = mb->get_entities_by_type_and_tag(0, MBENTITYSET, 
-                                            &geom_tag, &dim_ptr, 1, 
-                                            chsets, 1, false);
-
-      // for each child, get parents and do something with them
-    moab::Range::iterator ch_it, p_it;
-    for (ch_it = chsets.begin(); ch_it != chsets.end(); ch_it++) {
-        // get the children and put in child set list
-      psets.clear();
-      rval = mb ->get_parent_meshsets(*ch_it, psets);
-
-      rval = mb->tag_get_data(gid_tag, &(*ch_it), 1, &chgid);
-      
-        // print # parents
-      std::cout << ent_names[dim] << " " << chgid << " has " << psets.size() 
-                << " parents." << std::endl;
-
-      if (2 == dim) {
-        for (p_it = psets.begin(); p_it != psets.end(); p_it++) {
-          rval = mb->tag_get_data(gid_tag, &(*p_it), 1, &pgid);
-          rval = gt.get_sense(*ch_it, *p_it, sense);
-          if (moab::MB_SUCCESS != rval) continue;
-          std::cout << ent_names[dim+1] << " "   << pgid << ", " 
-                    << ent_names[dim] << " " << chgid << " sense is: ";
-          if (1==sense) std::cout << "FORWARD" << std::endl;
-          else std::cout << "REVERSE" << std::endl;
-        }
-      }
-      else if (1 == dim) {
-        sense_ents.clear();
-        senses.clear();
-        rval = gt.get_senses(*ch_it, sense_ents, senses);
-        if (moab::MB_SUCCESS != rval) continue;
-        for (unsigned int i = 0; i < sense_ents.size(); i++) {
-          rval = mb->tag_get_data(gid_tag, &sense_ents[i], 1, &pgid);
-          std::cout << ent_names[dim+1] << " "   << pgid << ", " 
-                    << ent_names[dim] << " " << chgid << " sense is: ";
-          if (-1 == senses[i]) std::cout << "REVERSED" << std::endl;
-          else if (0 == senses[i]) std::cout << "BOTH" << std::endl;
-          else if (1 == senses[i]) std::cout << "FORWARD" << std::endl;
-          else std::cout << "(invalid)" << std::endl;
-        }
-      }
-    }
-  } 
-}

diff --git a/examples/HelloMOAB.cpp b/examples/HelloMOAB.cpp
new file mode 100644
index 0000000..ee81de9
--- /dev/null
+++ b/examples/HelloMOAB.cpp
@@ -0,0 +1,62 @@
+/** @example HelloMOAB.cpp
+ * Description: read a mesh, get the entities.\n
+ * HelloMOAB is a simple test file which is used to read meshes from VTK file and test how many entities there are.\n
+ *
+ * To run: ./HelloMOAB <meshfile>\n
+ * (default values can run if users don't specify a mesh file)
+ */
+
+
+#include "moab/Core.hpp"
+
+using namespace moab;
+using namespace std;
+
+string test_file_name = string(MESH_DIR) + string("/3k-tri-sphere.vtk");
+
+int main( int argc, char** argv[] )
+{
+  Interface *iface = new Core;
+
+    // need option handling here for input filename
+  if (argc > 1){
+    //user has input a mesh file
+    test_file_name = argv[1];
+  }  
+    //load the mesh from vtk file
+  ErrorCode rval = iface->load_mesh( test_file_name );
+  assert( rval == MB_SUCCESS);
+
+    //get verts entities
+  Range verts;
+  rval = iface->get_entities_by_type(0, MBVERTEX, verts);
+  assert( rval == MB_SUCCESS);
+    //get edge entities
+  Range edges;
+  rval = iface->get_entities_by_type(0, MBEDGE, edges);
+  assert(rval == MB_SUCCESS);
+
+    //get triangular entities
+  Range tri;
+  rval = iface->get_entities_by_type(0, MBTRI, tri);
+  assert( rval == MB_SUCCESS);
+
+    //get quad entities
+  Range quads;
+  rval = iface->get_entities_by_type(0, MBQUAD, quads);
+  assert(rval == MB_SUCCESS);
+
+    //get hex entities
+  Range hex;
+  rval = iface->get_entities_by_type(0, MBHEX, hex);
+  assert(rval == MB_SUCCESS);
+
+   //output the number of entities
+  cout << "Number of vertices is " << verts.size() <<  endl;
+  cout << "Number of edges is " << edges.size() <<  endl;
+  cout << "Number of triangular faces is " << tri.size() <<  endl;
+  cout << "Number of quad faces is " << quads.size() <<  endl;
+  cout << "Number of hex is " << hex.size() <<  endl;
+  
+  return 0;
+}

diff --git a/examples/HelloMoabPar.cpp b/examples/HelloMoabPar.cpp
new file mode 100644
index 0000000..a5a71aa
--- /dev/null
+++ b/examples/HelloMoabPar.cpp
@@ -0,0 +1,154 @@
+/** @example HelloMoabPar.cpp \n
+ * \brief Read mesh into MOAB in parallel \n
+ * This example shows the simplest way of telling MOAB to read in parallel.
+ *
+ *    -#  Initialize MPI and get the rank and number of processors \n
+ *    -#  Process arguments (file name and options for parallel read) \n
+ *    -#  Initialize MOAB \n
+ *    -#  Load a partitioned file in parallel; \n
+ *    -#  retrieve shared entities on each processor \n
+ *    -#  Filter owned entities among shared ones on each processor \n
+ *    -#  Exchange ghost layers, and repeat the reports \n
+ *
+ * <b>To compile</b>: \n
+ *    make HelloMoabPar MOAB_DIR=<installdir>  \n
+ * <b>To run</b>: mpiexec -np 4 HelloMoabPar \n
+ *  (depending on your configuration, LD_LIBRARY_PATH may need to contain <hdf5>/lib folder)
+ *
+ */
+
+#include "moab/ParallelComm.hpp"
+#include "MBParallelConventions.h"
+#include "moab/Core.hpp"
+#include <iostream>
+
+using namespace moab;
+
+int main(int argc, char **argv)
+{
+  MPI_Init(&argc, &argv);
+
+  int nprocs, rank;
+  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+  std::string filename;
+  std::string options;
+  if (3 != argc)
+  {
+    if (rank == 0)
+    {
+      std::cout << "Usage: " << argv[0] << " <filename><options (separated by;)>\n ";
+    }
+    /* this file has a partition with 4 parts */
+    filename = "../MeshFiles/unittest/disk.h5m";
+    /*  Options for reading
+     *  - read in parallel
+     *  - use PARALLEL_PARTITION tag
+     *  - resolve shared entities after reading
+    */
+    options = "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;PARALLEL_RESOLVE_SHARED_ENTS";
+  }
+  else
+  {
+    filename = argv[1];
+    options = argv[2];
+  }
+  if (rank == 0)
+    std::cout << "reading file " << filename << "\n  with options:" << options <<
+      "\n  on " << nprocs << " processors\n";
+
+  // get MOAB instance and read the file with the specified options
+  Interface *mbImpl = new Core;
+  if (NULL == mbImpl) return 1;
+  ErrorCode rval = mbImpl->load_file(filename.c_str(), 0, options.c_str());
+  if (rval != MB_SUCCESS) return 1;
+
+  // get the ParallelComm instance
+  ParallelComm* pcomm = ParallelComm::get_pcomm(mbImpl, 0);
+  MPI_Comm comm = pcomm->comm();
+  if (0 == pcomm) return 1;
+
+  // get all shared entities with other processors
+  Range shared_ents;
+  rval = pcomm->get_shared_entities(-1, // -1 means all other processors                                    Range &shared_ents,
+      shared_ents);
+  if (rval != MB_SUCCESS) return 1;
+  /* Among shared entities, get those owned by the current processor
+   * For this, use a filter operation;
+   * Each shared entity is owned by exactly one processor;
+   * An entity could be simply-shared (with exactly one other processor) or
+   *  multi-shared.
+   */
+  Range owned_entities;
+  rval = pcomm->filter_pstatus(shared_ents, // pass entities that we want to filter
+      PSTATUS_NOT_OWNED, // status we are looking for
+      PSTATUS_NOT, // operation applied ; so it will return owned entities (!not_owned = owned)
+      -1, // this means all processors
+      &owned_entities);
+  if (rval != MB_SUCCESS) return 1;
+  unsigned int nums[4]={0}; // to store the owned entities per dimension
+  for (int i=0; i<3; i++)
+  {
+    nums[i]=(int)owned_entities.num_of_dimension(i);
+  }
+  int * rbuf;
+  if (rank==0)
+    rbuf = (int *)malloc(nprocs*4*sizeof(int));
+  MPI_Gather( nums, 4, MPI_INT, rbuf, 4, MPI_INT, 0, comm);
+  // print the stats gathered:
+  if (rank == 0)
+  {
+    for (int i=0; i<nprocs; i++)
+    {
+      std::cout << " shared, owned entities on proc " << i << " :" << rbuf[4*i] << " verts, " <<
+          rbuf[4*i+1] << " edges, " << rbuf[4*i+2] << " faces\n";
+    }
+
+  }
+
+  /*
+   * Now exchange 1 layer of ghost elements, using vertices as bridge
+   *   we could have done this as part of reading process, by passing an extra read option
+   *    ";PARALLEL_GHOSTS=2.0.1.0"
+   */
+  rval = pcomm->exchange_ghost_cells(2, // int ghost_dim,
+                                     0, // int bridge_dim,
+                                     1, //int num_layers,
+                                     0, //int addl_ents,
+                                     true); // bool store_remote_handles);
+  if (rval != MB_SUCCESS) return 1;
+
+  // repeat the reports, after ghost exchange
+  shared_ents.clear();
+  owned_entities.clear();
+  rval = pcomm->get_shared_entities(-1, // -1 means all other processors                                    Range &shared_ents,
+        shared_ents);
+  if (rval != MB_SUCCESS) return 1;
+  rval = pcomm->filter_pstatus(shared_ents,
+        PSTATUS_NOT_OWNED,
+        PSTATUS_NOT,
+        -1,
+        &owned_entities);
+  if (rval != MB_SUCCESS)  return 1;
+
+  // find out how many shared entities of each dimension are owned on this processor
+  for (int i=0; i<3; i++)
+    nums[i]=(int)owned_entities.num_of_dimension(i);
+
+  // gather the statistics on processor 0
+  MPI_Gather( nums, 4, MPI_INT, rbuf, 4, MPI_INT, 0, comm);
+  if (rank == 0)
+  {
+    std::cout << " \n\n After exchanging one ghost layer: \n";
+    for (int i=0; i<nprocs; i++)
+    {
+      std::cout << " shared, owned entities on proc " << i << " :" << rbuf[4*i] << " verts, " <<
+          rbuf[4*i+1] << " edges, " << rbuf[4*i+2] << " faces\n";
+    }
+    free(rbuf);
+  }
+  MPI_Finalize();
+
+  return 0;
+}

diff --git a/examples/Makefile.am b/examples/Makefile.am
deleted file mode 100644
index 21e6da3..0000000
--- a/examples/Makefile.am
+++ /dev/null
@@ -1,65 +0,0 @@
-# NOTE:  The 'makefile' in the *installed* examples directory is generated
-#        using the install-data-hook target below.  This logic assumes that:
-#        1) All examples are listed in check_PROGRAMS
-#        2) All examples have a single source file with the same name (case
-#           sensitive) as the example executable with a .cpp suffix.
-
-check_PROGRAMS = FileRead \
-                 GeomSetHierarchy \
-                 GetEntities \
-		 ObbTree \
-                 SetsNTags \
-                 SkinMesh \
-                 SurfArea 
-
-SRCDIR = $(top_srcdir)/examples
-
-LDADD = ../src/libMOAB.la
-AM_CPPFLAGS += -I../src \
-               -I$(srcdir)/../src \
-               -I$(srcdir)/../src/parallel \
-               -I$(srcdir)/../src/oldinc \
-               -DSRCDIR=$(SRCDIR)
-
-FileRead_SOURCES = FileRead.cpp
-GeomSetHierarchy_SOURCES = GeomSetHierarchy.cpp
-GetEntities_SOURCES = simple/GetEntities.cpp
-SetsNTags_SOURCES = SetsNTags.cpp
-SkinMesh_SOURCES = SkinMesh.cpp
-SurfArea_SOURCES = SurfArea.cpp
-ObbTree_SOURCES = ObbTree.cpp
-
-exampledir = ${docdir}/examples
-nobase_example_DATA = \
-               examples.make \
-               FileRead.cpp \
-               GeomSetHierarchy.cpp \
-               simple/GetEntities.cpp \
-               simple/makefile \
-	       ObbTree.cpp \
-               SetsNTags.cpp \
-               SkinMesh.cpp \
-               SurfArea.cpp 
-               
-if ENABLE_imesh
-  imesh_DIR = itaps
-else
-  imesh_DIR = 
-endif 
-
-SUBDIRS = $(imesh_DIR)
-
-ex_make = $(DESTDIR)$(exampledir)/makefile
-install-data-hook:
-	$(AM_V_at)rm -f $(ex_make)
-	$(AM_V_at)mv $(DESTDIR)$(exampledir)/examples.make $(ex_make)
-	$(AM_V_at)echo "all: $(check_PROGRAMS)" >>$(ex_make)
-	$(AM_V_at)rule='	$$(CXX) -o $$@ $$< $$(CXXFLAGS) $$(MOAB_INCLUDES) $$(MOAB_LIBS_LINK)'; \
-	for example in $(check_PROGRAMS); do \
-	  echo >>$(ex_make); \
-	  echo "$${example}: $${example}.cpp" >>$(ex_make); \
-	  echo "$$rule" >>$(ex_make); \
-	done
-
-uninstall-hook:
-	$(AM_V_at)rm -f $(DESTDIR)$(exampledir)/makefile

diff --git a/examples/ObbTree.cpp b/examples/ObbTree.cpp
deleted file mode 100644
index 220681f..0000000
--- a/examples/ObbTree.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-// simple example construct obb tree and ray-tracing the tree
-// it reads triangle mesh, construct obb tree and get intersection distances
-
-#include "moab/Core.hpp"
-#include "moab/Range.hpp"
-#include "moab/OrientedBoxTreeTool.hpp"
-#include <iostream>
-#include <math.h>
-
-int main(int argc, char **argv) {
-  if (1 == argc) {
-    std::cout << "Usage: " << argv[0] << " <filename>" << std::endl;
-    return 0;
-  }
-
-  // instantiate & load a mesh from a file
-  moab::Core *mb = new moab::Core();
-  moab::ErrorCode rval = mb->load_mesh(argv[1]);
-
-  // get all triangles
-  moab::EntityHandle tree_root;
-  moab::Range tris;
-  //moab::OrientedBoxTreeTool::Settings settings;
-
-  rval = mb->get_entities_by_type( 0, moab::MBTRI, tris );
-  if (rval != moab::MB_SUCCESS) {
-    std::cerr << "Couldn't get triangles." << std::endl;
-    return 1;
-  }
-
-  // build OBB trees for all triangles
-  moab::OrientedBoxTreeTool tool(mb);
-  //rval = tool.build(tris, tree_root, &settings);
-  rval = tool.build(tris, tree_root);
-  if (rval != moab::MB_SUCCESS) {
-    std::cerr << "Could'nt build tree." << std::endl;    
-    return 1;
-  }
-  
-  // build box
-  double box_center[3], box_axis1[3], box_axis2[3], box_axis3[3], pnt_start[3], ray_length;
-  rval = tool.box(tree_root, box_center, box_axis1, box_axis2, box_axis3);
-  if (rval != moab::MB_SUCCESS) {
-    std::cerr << "Couldn't get box for tree root set.";
-    return 1;
-  }
-
-  ray_length = 2.*sqrt(box_axis1[0]*box_axis1[0] + box_axis1[1]*box_axis1[1] +
-		       box_axis1[2]*box_axis1[2]);
-  
-  // do ray-tracing from box center side to x direction
-  std::vector<double> intersections;
-  std::vector<moab::EntityHandle> intersection_facets;
-
-  for (int i=0; i<3; i++)
-    pnt_start[i] = box_center[i]-box_axis1[i];
-
-  if (ray_length>0) // normalize ray direction
-    for (int j=0; j<3; j++)
-      box_axis1[j]=2*box_axis1[j]/ray_length;
-  rval = tool.ray_intersect_triangles(intersections, intersection_facets, 
-				      tree_root, 10e-12, pnt_start, box_axis1,
-				      &ray_length);
-  if (rval != moab::MB_SUCCESS) {
-    std::cerr << "Couldn't ray tracing.";
-    return 1;
-  }
-  
-  std::cout << "ray start point: " << pnt_start[0] << " "
-	    << pnt_start[1] << " " << pnt_start[2] << std::endl;
-  std::cout << " ray direction: " << box_axis1[0] << " " << box_axis1[1] << " " << box_axis1[2] << "\n";
-  std::cout << "# of intersections : " << intersections.size() << std::endl;
-  std::cout << "intersection distances are on";
-  for (unsigned int i = 0; i < intersections.size(); i++) {
-    std::cout << " " << intersections[i];
-  }
-  std::cout << " of ray length " << ray_length << std::endl;
-
-  return 0;
-}

diff --git a/examples/README b/examples/README
deleted file mode 100644
index 7b22564..0000000
--- a/examples/README
+++ /dev/null
@@ -1,56 +0,0 @@
-This directory contains examples of some of MOAB's key functionality.
-Each example described here corresponds to a source file.  To make all
-examples, enter 'make check'.  To make a specific example, list that
-example name on the make command line.  For example,
-
-  make FileRead
-
-will make the FileRead example, while
-
-  make check
-
-will make all the examples.
-
-The GetEntities example is located in the "simple" subdirectory.  The
-makefile there indicates how to build a program linked to MOAB using a
-simple makefile.
-
-The Makefile.am in the main examples directory illustrates how to
-build a program linked to MOAB using a GNU autotools build system.
-
-For more information on these examples, refer to the MOAB Code
-Examples webpage at
-    http://trac.mcs.anl.gov/projects/ITAPS/wiki/CodeExamples
-
-
-Simple Examples
-===============
-    simple/GetEntities: get the number of entities of each dimension
-
-    SetsNTags: query the sets in a mesh and tags on those sets
-
-
-General Mesh Query & Manipulation
-=================================
-    SkinMesh: compute the outer faces of a mesh
-
-    SurfArea: compute the surface area of the skin of a mesh
-
-    ObbTree: construct an obb tree from input triangles and do ray-tracing
-
-    KDTree: construct a kD-tree from a hexahedral mesh and then search
-            for some points
-
-
-Mesh Import
-===========
-    FileRead: file reader example
-
-
-Meta-Data
-=========
-    GeomSetHierarchy: read and query geometric model information
-
-ITAPS
-=====
-    itaps/TagIterate: get a pointer to tag memory, allowing bypass of API for getting/setting tags

diff --git a/examples/README.FileReader b/examples/README.FileReader
deleted file mode 100644
index 8b7e493..0000000
--- a/examples/README.FileReader
+++ /dev/null
@@ -1,12 +0,0 @@
-Mesh readers and writers communicate mesh into/out of MOAB from/to disk files.  
-Reading a mesh often involves importing large sets of data, for example coordinates of all the nodes in the mesh.  Normally, this process would involve reading data from the file into a temporary data buffer, then copying data from there into its destination in MOAB.  To avoid the expense of copying data, MOAB has implemented a reader/writer interface that provides direct access to blocks of memory used to represent mesh.
-The reader interface, declared in MBReadUtilIface, is used to request blocks of memory for storing coordinate positions and element connectivity.  The pointers returned from these functions point to the actual memory used to represent those data in MOAB.  Once data is written to that memory, no further copying is done.  This not only saves time, but it also eliminates the need to allocate a large memory buffer for intermediate storage of these data. 
-
-In this example, Triangle output files are read into MOAB. The database is saved into a file specified by the user, as the second argument
-
-usage 
-FileRead <triangle_file_base><output_file>
-example provided
-$>  FileRead A.1 out.vtk
-
-It is assumed that the <>.node file and <>.ele files are existing.  

diff --git a/examples/ReduceExchangeTags.cpp b/examples/ReduceExchangeTags.cpp
new file mode 100644
index 0000000..6c2e7de
--- /dev/null
+++ b/examples/ReduceExchangeTags.cpp
@@ -0,0 +1,228 @@
+/** @example ReduceExchangeTags.cpp
+ * \brief Example program that shows the use case for performing tag data exchange
+ * between parallel processors in order to sync data on shared entities. The reduction
+ * operation on tag data is also shown where the user can perform any of the actions supported
+ * by MPI_Op on data residing on shared entities. \n
+ *
+ * <b>This example </b>:
+ *    -# Initialize MPI and instantiate MOAB
+ *    -# Get user options: Input mesh file name, tag name (default: USERTAG), tag value (default: 1.0)
+ *    -# Create the root and partition sets
+ *    -# Instantiate ParallelComm and read the mesh file in parallel using appropriate options
+ *    -# Create two tags: USERTAG_EXC (exchange) and USERTAG_RED (reduction)
+ *    -# Set tag data and exchange shared entity information between processors
+ *      -# Get entities in all dimensions and set local (current rank, dimension) dependent data for
+ *     exchange tag (USERTAG_EXC)
+ *      -# Perform exchange of tag data so that data on shared entities are synced via ParallelCommunicator.
+ *    -#  Set tag data and reduce shared entity information between processors using MPI_SUM
+ *      -#  Get higher dimensional entities in the current partition and set local (current rank)
+ *     dependent data for reduce tag (USERTAG_EXC)
+ *      -#  Perform the reduction operation (MPI_SUM) on shared entities via ParallelCommunicator.
+ *    -#  Destroy the MOAB instance and finalize MPI
+ *
+ * <b>To run:</b> \n mpiexec -n 2 ./ReduceExchangeTags <mesh_file><tag_name><tag_value> \n
+ * <b>Example:</b> \n mpiexec -n 2 ./ReduceExchangeTags ../MeshFiles/unittest/64bricks_1khex.h5m USERTAG 100 \n
+ *
+ */
+
+#include "moab/ParallelComm.hpp"
+#include "MBParallelConventions.h"
+#include "moab/Core.hpp"
+#include <iostream>
+#include <string>
+#include <sstream>
+
+using namespace moab;
+
+// Error routines for use with MOAB API
+#define CHKERR(CODE, MSG)                                 \
+  do {                                                    \
+    if (MB_SUCCESS != (CODE)) {                           \
+      std::string errstr;  mbi->get_last_error(errstr);   \
+      std::cerr << errstr << std::endl;                   \
+      std::cerr << MSG << std::endl;                      \
+      MPI_Finalize();                                     \
+    }                                                     \
+  } while(false)
+
+// Error routines for use with MPI API
+#define MPICHKERR(CODE, MSG)                              \
+  do {                                                    \
+    if (0 != CODE) {                                      \
+      std::cerr << MSG << std::endl;                      \
+      MPI_Finalize();                                     \
+    }                                                     \
+  } while(false)
+
+#define dbgprint(MSG)                                \
+  do {                                              \
+      if (!rank) std::cerr << MSG << std::endl;     \
+  } while(false)
+
+#define dbgprintall(MSG)                                      \
+  do {                                                        \
+      std::cerr << "[" << rank << "]: " << MSG << std::endl;  \
+  } while(false)
+
+
+// Function to parse input parameters
+ErrorCode get_file_options(int argc, char **argv,
+                           std::string& filename,
+                           std::string& tagName,
+                           double&      tagValues)
+{
+  // get mesh filename
+  if (argc > 1) filename = std::string(argv[1]);
+  else filename = std::string(MESH_DIR) + std::string("/64bricks_1khex.h5m");
+
+  // get tag selection options
+  if (argc > 2) tagName = std::string(argv[2]);
+  else tagName = "USERTAG";
+
+  if (argc > 3)  tagValues = atof(argv[3]);
+  else tagValues = 1.0;
+
+  return MB_SUCCESS;
+}
+
+//
+// Start of main test program
+//
+int main(int argc, char **argv)
+{
+  ErrorCode err;
+  int ierr, rank;
+  std::string filename, tagName;
+  double tagValue;
+  MPI_Comm comm = MPI_COMM_WORLD;
+  /// Parallel Read options:
+  ///   PARALLEL = type {READ_PART}
+  ///   PARTITION = PARALLEL_PARTITION : Partition as you read
+  ///   PARALLEL_RESOLVE_SHARED_ENTS : Communicate to all processors to get the shared adjacencies consistently in parallel
+  ///   PARALLEL_GHOSTS : a.b.c
+  ///                   : a = 3 - highest dimension of entities
+  ///                   : b = 0 -
+  ///                   : c = 1 - number of layers
+  ///   PARALLEL_COMM = index
+  std::string read_options = "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;PARALLEL_RESOLVE_SHARED_ENTS;PARTITION_DISTRIBUTE;PARALLEL_GHOSTS=3.0.1;PARALLEL_COMM=0";
+
+  // Print usage if not enough arguments
+  if (argc < 1) {
+    std::cerr << "Usage: ";
+    std::cerr << argv[0] << " <file_name><tag_name><tag_value>" << std::endl;
+    std::cerr << "file_name    : mesh file name" << std::endl;
+    std::cerr << "tag_name     : name of tag to add to mesh" << std::endl;
+    std::cerr << "tag_value    : a double valued string to set for highest-dimensional entities in the mesh for the named tag" << std::endl;
+
+    ierr = MPI_Finalize();
+    MPICHKERR(ierr, "MPI_Finalize failed; Aborting");
+
+    return 1;
+  }
+
+  // Initialize MPI first
+  ierr = MPI_Init(&argc, &argv);
+  MPICHKERR(ierr, "MPI_Init failed");
+
+  ierr = MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+  MPICHKERR(ierr, "MPI_Comm_rank failed");
+
+  dbgprint( "********** reduce_exchange_tags **********\n" );
+
+  // Create the moab instance
+  Interface *mbi = new Core();
+  CHKERR(NULL == mbi, "MOAB constructor failed");
+
+  // Get the input options
+  err = get_file_options(argc, argv, filename, tagName, tagValue);
+  CHKERR(err, "get_file_options failed");
+
+  // Print out the input parameters
+  dbgprint( " Input Parameters - " );
+  dbgprint( "   Filenames: " << filename );
+  dbgprint( "   Tag: Name=" << tagName << " Value=" << tagValue << std::endl );
+
+  // Create root sets for each mesh.  Then pass these
+  // to the load_file functions to be populated.
+  EntityHandle rootset, partnset;
+  err = mbi->create_meshset(MESHSET_SET, rootset);
+  CHKERR(err, "Creating root set failed");
+  err = mbi->create_meshset(MESHSET_SET, partnset);
+  CHKERR(err, "Creating partition set failed");
+
+  // Create the parallel communicator object with the partition handle associated with MOAB
+  ParallelComm *parallel_communicator = ParallelComm::get_pcomm( mbi, partnset, &comm );
+
+  // Load the file from disk with given options
+  err = mbi->load_file( filename.c_str(), &rootset, read_options.c_str() );
+  CHKERR(err, "MOAB::load_file failed");
+
+  // Create two tag handles: Exchange and Reduction operations
+  dbgprint( "-Creating tag handle " << tagName << "..." );
+  Tag tagReduce, tagExchange;
+  {
+    std::stringstream sstr;
+    // Create the exchange tag: default name = USERTAG_EXC
+    sstr << tagName << "_EXC";
+    err = mbi->tag_get_handle(sstr.str().c_str(), 1, MB_TYPE_INTEGER, tagExchange, MB_TAG_CREAT|MB_TAG_DENSE, &tagValue);
+    CHKERR(err, "Retrieving tag handles failed");
+
+    // Create the exchange tag: default name = USERTAG_RED
+    sstr.str(""); sstr << tagName << "_RED";
+    err = mbi->tag_get_handle(sstr.str().c_str(), 1, MB_TYPE_DOUBLE, tagReduce, MB_TAG_CREAT|MB_TAG_DENSE, &tagValue);
+    CHKERR(err, "Retrieving tag handles failed");
+  }
+
+  // Perform exchange tag data
+  dbgprint( "-Exchanging tags between processors " );
+  {
+    Range partEnts, dimEnts;
+    for (int dim = 0; dim <= 3; dim++) {
+      // Get all entities of dimension = dim
+      err = mbi->get_entities_by_dimension(rootset, dim, dimEnts, false);
+
+      std::vector<int> tagValues(dimEnts.size(), static_cast<int>(tagValue)*(rank+1)*(dim+1));
+      // Set local tag data for exchange
+      err = mbi->tag_set_data(tagExchange, dimEnts, &tagValues[0]);
+      CHKERR(err, "Setting local tag data failed during exchange phase");
+      // Merge entities into parent set
+      partEnts.merge(dimEnts);
+    }
+
+    // Exchange tags between processors
+    err = parallel_communicator->exchange_tags(tagExchange, partEnts);
+    CHKERR(err, "Exchanging tags between processors failed");
+  }
+
+  // Perform reduction of tag data
+  dbgprint( "-Reducing tags between processors " );
+  {
+    Range partEnts;
+    // Get all higher dimensional entities belonging to current partition
+    err = parallel_communicator->get_part_entities(partEnts);
+    CHKERR(err, "ParallelComm::get_part_entities failed");
+
+    // Output what is in current partition sets
+    dbgprintall( "Number of Partitioned entities: " <<  partEnts.size() );
+    MPI_Barrier(comm);
+
+    // Set local tag data for reduction
+    std::vector<double> tagValues(partEnts.size(), tagValue*(rank+1));
+    err = mbi->tag_set_data(tagReduce, partEnts, &tagValues[0]);
+    CHKERR(err, "Setting local tag data failed during reduce phase");
+
+    Range dummy;
+    // Reduce tag data using MPI_SUM on the interface between partitions
+    err = parallel_communicator->reduce_tags(tagReduce, MPI_SUM, dummy/*partEnts*/);
+    CHKERR(err, "Reducing tags between processors failed");
+  }
+  // Write out to output file to visualize reduction/exchange of tag data
+  mbi->write_file("test.h5m", "H5M", "PARALLEL=WRITE_PART");
+
+  // Done, cleanup
+  delete mbi;
+
+  dbgprint( "\n********** reduce_exchange_tags DONE! **********" );
+  MPI_Finalize();
+  return 0;
+}

diff --git a/examples/SetsNTags.cpp b/examples/SetsNTags.cpp
deleted file mode 100644
index 9930891..0000000
--- a/examples/SetsNTags.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-#include "moab/Core.hpp"
-#include "moab/Interface.hpp"
-#include "moab/Range.hpp"
-
-#ifdef USE_MPI
-#include "moab_mpi.h"
-#endif
-
-#include <iostream>
-
-int main(int argc, char **argv) {
-    // get the material set tag handle
-  moab::Tag mtag;
-  moab::ErrorCode rval;
-  const char *tag_nms[] = {"MATERIAL_SET", "DIRICHLET_SET", "NEUMANN_SET"};
-  moab::Range sets, set_ents;
-
-    // instantiate & load a file
-  moab::Interface *mb = new moab::Core();
-  const char *par_opt = "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;PARTITION_DISTRIBUTE;PARALLEL_RESOLVE_SHARED_ENTS;SETS=SETS";
-
-  bool parallel = false;
-  if (argc > 2 && !strcmp(argv[1], "-p")) parallel = true;
-  else if (argc == 1) {
-    std::cout << "Usage: " << argv[0] << "[-p] <filename>" << std::endl;
-    return 0;
-  }
-
-  if (parallel) 
-    rval = mb->load_file(argv[argc-1], 0, par_opt);
-  else
-    rval = mb->load_file(argv[argc-1]);
-  if (moab::MB_SUCCESS != rval) return 1;
-
-    // loop over set types
-  for (int i = 0; i < 3; i++) {
-    rval = mb->tag_get_handle(tag_nms[i], 1, moab::MB_TYPE_INTEGER, mtag);
-    if (moab::MB_SUCCESS != rval) return 1;
-
-      // get all the sets of that type in the mesh
-    sets.clear();
-    rval = mb->get_entities_by_type_and_tag(0, moab::MBENTITYSET, &mtag,
-                                            NULL, 1, sets);
-    if (moab::MB_SUCCESS != rval) return 1;
-
-      // iterate over each set, getting entities
-    moab::Range::iterator set_it;
-    for (set_it = sets.begin(); set_it != sets.end(); set_it++)  {
-      moab::EntityHandle this_set = *set_it;
-
-        // get the id for this set
-      int set_id;
-      rval = mb->tag_get_data(mtag, &this_set, 1, &set_id);
-      if (moab::MB_SUCCESS != rval) return 1;
-
-        // get the entities in the set, recursively
-      rval = mb->get_entities_by_handle(this_set, set_ents, true);
-      if (moab::MB_SUCCESS != rval) return 1;
-
-      std::cout << tag_nms[i] << " " << set_id << " has " 
-                << set_ents.size() << " entities:" << std::endl;
-      set_ents.print("   ");
-      set_ents.clear();
-    }
-  }
-
-    // do the same for all sets
-  sets.clear();
-  rval = mb->get_entities_by_type(0, moab::MBENTITYSET, sets);
-  if (moab::MB_SUCCESS != rval) return 1;
-
-    // print the sets
-  rval = mb->list_entities(sets);
-  if (moab::MB_SUCCESS != rval) return 1;
-
-  rval = mb->list_entities(NULL, 1);
-  
-#ifdef USE_MPI
-  if (parallel) {
-    MPI_Barrier(MPI_COMM_WORLD);
-    std::cout << std::flush;
-    std::cerr << std::flush;
-  }
-#endif
-
-  delete mb;
-}

diff --git a/examples/SkinMesh.cpp b/examples/SkinMesh.cpp
deleted file mode 100644
index dc45212..0000000
--- a/examples/SkinMesh.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-#include <iostream>
-#include <stdlib.h>
-#include "MBCore.hpp"
-#include "MBRange.hpp"
-#include "MBTagConventions.hpp"
-
-// Hold edges in an array of vertex handles.
-struct edge {
-  MBEntityHandle v0;                                                                                                                      
-  MBEntityHandle v1;
-};
-                                                                                                                                         
-// edge structure comparision function for qsort
-// If the first vertex handle is the same, compare the second.
-int compare_edge(const void *a, const void *b) {
-  struct edge *ia = (struct edge *)a;
-  struct edge *ib = (struct edge *)b;
-  if(ia->v0 == ib->v0) {
-    return (int)(100.f*ia->v1 - 100.f*ib->v1);
-  } else {
-    return (int)(100.f*ia->v0 - 100.f*ib->v0);
-  }
-}
-
-// This skinner is fast partly because it assumes that no edges exist in the MOAB 
-// instance. Checking to see if an edge exists before creating a new one is slow. 
-MBErrorCode skin_tris( MBInterface *mb, MBRange tris, MBRange &skin_edges ) {    
-  
-  // Empty the output range and make sure that the input range is only tris
-  skin_edges.clear(); 
-  if(tris.empty()) return MB_ENTITY_NOT_FOUND;
-  if(!tris.all_of_type(MBTRI)) return MB_FAILURE;
-
-  // Remove edges from the instance.
-  int n_edges;
-  MBErrorCode rval = mb->get_number_entities_by_type( 0, MBEDGE, n_edges );
-  if(MB_SUCCESS != rval) return rval;
-  if(0 != n_edges) {
-    std::cerr << "skin_tris: failed because " << n_edges 
-              << " edges exist in the MOAB instance" << std::endl;
-    return MB_FAILURE;
-  }      
-
-  // Get connectivity. Do not create MBEdges.
-  edge *edges = new edge[3*tris.size()];
-  int n_verts;
-  int ii = 0;
-  for(MBRange::iterator i=tris.begin(); i!=tris.end(); i++) {
-    const MBEntityHandle *conn;
-    rval = mb->get_connectivity( *i, conn, n_verts );
-    if(MB_SUCCESS != rval) return rval;
-    if(3 != n_verts) return MB_FAILURE;
-    // points should not be degenerate
-    if(conn[0]==conn[1] || conn[1]==conn[2] || conn[2]==conn[0]) {
-      std::cerr << "skin_tris: degenerate triangle" << std::endl;
-      return MB_FAILURE;
-    }
-
-    // make edges
-    edges[3*ii+0].v0 = conn[0];
-    edges[3*ii+0].v1 = conn[1];
-    edges[3*ii+1].v0 = conn[1];
-    edges[3*ii+1].v1 = conn[2];
-    edges[3*ii+2].v0 = conn[2];
-    edges[3*ii+2].v1 = conn[0];
-    ii++;
-  }
-
-  // Ensure that the first vertex handle is the lowest
-  for(unsigned int i=0; i<3*tris.size(); ++i) {
-    if(edges[i].v0 > edges[i].v1) {
-      MBEntityHandle temp = edges[i].v0;
-      edges[i].v0 = edges[i].v1;
-      edges[i].v1 = temp;
-    }
-  }
-
-  // Sort by first handle, then second handle.
-  qsort(edges, 3*tris.size(), sizeof(struct edge), compare_edge);    
-
-  // Go through array, saving edges that are not paired.
-  for(unsigned int i=0; i<3*tris.size(); i++) {
-    // If the last edge has not been paired, create it. This avoids overrunning
-    // the edges array with i+1.
-    if(3*tris.size()-1 == i) {
-      const MBEntityHandle conn[2] = {edges[i].v0, edges[i].v1};
-      MBEntityHandle edge;
-      rval = mb->create_element( MBEDGE, conn, 2, edge );
-      if(MB_SUCCESS != rval) return rval;
-      skin_edges.insert(edge);
-    
-    // If a match exists, skip ahead
-    } else if(edges[i].v0==edges[i+1].v0 && edges[i].v1==edges[i+1].v1) {
-      i++;
-      // test to make sure surface is manifold
-      while( edges[i].v0==edges[i+1].v0 && edges[i].v1==edges[i+1].v1 ) {
-        std::cout << "find_skin WARNING: non-manifold edge" << std::endl;
-        mb->list_entity( edges[i].v0 );
-        mb->list_entity( edges[i].v1 );
-        ++i;
-      }
-    // otherwise a skin edge has been found
-    } else {
-      const MBEntityHandle conn[2] = {edges[i].v0, edges[i].v1};
-      MBEntityHandle edge;
-      rval = mb->create_element( MBEDGE, conn, 2, edge );
-      if(MB_SUCCESS != rval) return rval;
-      skin_edges.insert( edge );
-    } 
-  }
-  delete[] edges;
-  return MB_SUCCESS;
-}
-
-
-// Skin triangles to recover edges.
-// Triangles are contained in surface sets.
-int main(int argc, char **argv) {
-  if (1 == argc) {
-  std::cout << "Usage: " << argv[0] << " <filename>" << std::endl;
-    return 0;
-  }     
-
-  // get MOAB instance and read the file                                                                                                  
-  MBCore *mb = new MBCore();
-  MBErrorCode rval = mb->load_file(argv[1]);
-  if(MB_SUCCESS != rval) return 0;
-
-  // this optimized skinner requires removing all MBEdges from the MOAB instance
-  MBRange edges;
-  rval = mb->get_entities_by_type( 0, MBEDGE, edges );
-  if(MB_SUCCESS != rval) return 0;
-  if( !edges.empty() ) std::cout << "Warning: deleting all MBEdges" << std::endl;
-  rval = mb->delete_entities( edges );
-  if(MB_SUCCESS != rval) return 0;
-
-  // get surface sets
-  MBTag geom_tag;
-  rval = mb->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, geom_tag );
-  if(MB_SUCCESS != rval) return 0;
-  MBRange surf_sets;
-  int two = 2;
-  void *dim[] = {&two};                                                                                   
-  rval = mb->get_entities_by_type_and_tag( 0, MBENTITYSET, &geom_tag,                                                                
-                                           dim, 1, surf_sets );
-  if(MB_SUCCESS != rval) return 0;
-
-  // skin each surface
-  for(MBRange::iterator i=surf_sets.begin(); i!=surf_sets.end(); ++i) {
-
-    // get triangles in the surface set
-    MBRange tris;
-    rval = mb->get_entities_by_type( *i, MBTRI, tris );
-    if(MB_SUCCESS != rval) return 0;
-
-    // call the skinning function
-    MBRange skin_edges;
-    rval = skin_tris( mb, tris, skin_edges );
-    if(MB_SUCCESS != rval) return 0;
-
-    // do something with the result
-    std::cout << "surface has " << skin_edges.size() << " skin edges" << std::endl;
-
-    // remove the edges for the optimized skinner
-    rval = mb->delete_entities( skin_edges );
-    if(MB_SUCCESS != rval) return 0;    
-  }
-}  

diff --git a/examples/StructuredMeshSimple.cpp b/examples/StructuredMeshSimple.cpp
new file mode 100644
index 0000000..25aa08f
--- /dev/null
+++ b/examples/StructuredMeshSimple.cpp
@@ -0,0 +1,110 @@
+/** @example StructuredMeshSimple.cpp
+ * \brief Show creation and query of structured mesh, serial or parallel, through MOAB's structured mesh interface.
+ * This is an example showing creation and query of a 3D structured mesh.  In serial, a single N*N*N block of elements
+ * is created; in parallel, each proc gets an N*N*N block, with blocks arranged in a 1d column, sharing vertices
+ * and faces at their interfaces (proc 0 has no left neighbor and proc P-1 no right neighbor).
+ * Each square block of hex elements is then referenced by its ijk parameterization.
+ * 1D and 2D examples could be made simply by changing the dimension parameter passed into the MOAB functions. \n
+ *
+ * <b>This example </b>:
+ *    -# Instantiate MOAB and get the structured mesh interface
+ *    -# Decide what the local parameters of the mesh will be, based on parallel/serial and rank.
+ *    -# Create a N^d structured mesh, which includes (N+1)^d vertices and N^d elements.
+ *    -# Get the vertices and elements from moab and check their numbers against (N+1)^d and N^d, resp.
+ *    -# Loop over elements in d nested loops over i, j, k; for each (i,j,k):
+ *      -# Get the element corresponding to (i,j,k)
+ *      -# Get the connectivity of the element
+ *      -# Get the coordinates of the vertices comprising that element
+ *    -# Release the structured mesh interface and destroy the MOAB instance
+ *
+ * <b> To run: </b> ./structuredmesh [d [N] ] \n
+ * (default values so can run w/ no user interaction)
+ */
+
+#include "moab/Core.hpp"
+#include "moab/ScdInterface.hpp"
+#include "moab/ProgOptions.hpp"
+#include "moab/CN.hpp"
+#include <iostream>
+#include <vector>
+
+using namespace moab;
+
+int main(int argc, char **argv) 
+{
+  int N = 10, dim = 3;
+
+  ProgOptions opts;
+  opts.addOpt<int>(std::string("dim,d"), std::string("Dimension of mesh (default=3)"),
+                   &dim);
+  opts.addOpt<int>(std::string(",n"), std::string("Number of elements on a side (default=10)"),
+                   &N);
+  opts.parseCommandLine(argc, argv);
+  
+    // 0. Instantiate MOAB and get the structured mesh interface
+  Interface *mb = new Core();
+  ScdInterface *scdiface;
+  ErrorCode rval = mb->query_interface(scdiface); // get a ScdInterface object through moab instance
+  if (MB_SUCCESS != rval) return rval;
+
+    // 1. Decide what the local parameters of the mesh will be, based on parallel/serial and rank.
+  int ilow = 0, ihigh = N;
+  int rank = 0, nprocs = 1;
+#ifdef USE_MPI
+  MPI_Comm_size(MPI_COMM_WORLD, &nprocs); MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+  ilow = rank*N; ihigh = ilow + N;
+#endif  
+
+    // 2. Create a N^d structured mesh, which includes (N+1)^d vertices and N^d elements.
+  ScdBox *box;
+  rval = scdiface->construct_box(HomCoord(ilow, (dim>1?0:-1), (dim>2?0:-1)), // use in-line logical tests to handle dimensionality
+                                 HomCoord(ihigh, (dim>1?N:-1), (dim>2?N:-1)), 
+                                 NULL, 0, // NULL coords vector and 0 coords (don't specify coords for now)
+                                 box);    // box is the structured box object providing the parametric
+                                          // structured mesh interface for this rectangle of elements
+  if (MB_SUCCESS != rval) return rval;
+
+    // 3. Get the vertices and elements from moab and check their numbers against (N+1)^d and N^d, resp.
+  Range verts, elems;
+  rval = mb->get_entities_by_dimension(0, 0, verts); // first '0' specifies "root set", or entire MOAB instance, second the entity dimension being requested
+  if (MB_SUCCESS != rval) return rval;
+  rval = mb->get_entities_by_dimension(0, dim, elems);
+  if (MB_SUCCESS != rval) return rval;
+
+#define MYSTREAM(a) if (!rank) std::cout << a << std::endl
+  
+  if (pow(N,dim) == (int) elems.size() && pow(N+1,dim) == (int) verts.size()) { // expected #e and #v are N^d and (N+1)^d, resp.
+#ifdef USE_MPI
+    MYSTREAM("Proc 0: ");
+#endif
+    MYSTREAM("Created " << elems.size() << " " << CN::EntityTypeName(mb->type_from_handle(*elems.begin())) 
+             << " elements and " << verts.size() << " vertices." << std::endl);
+  }
+  else
+    std::cout << "Created the wrong number of vertices or hexes!" << std::endl;
+  
+    // 4. Loop over elements in 3 nested loops over i, j, k; for each (i,j,k):
+  std::vector<double> coords(3*pow(N+1,dim));
+  std::vector<EntityHandle> connect;
+  for (int k = 0; k < (dim>2?N:1); k++) {
+    for (int j = 0; j < (dim>1?N:1); j++) {
+      for (int i = 0; i < N-1; i++) {
+          // 4a. Get the element corresponding to (i,j,k)
+        EntityHandle ehandle = box->get_element(i, j, k);
+        if (0 == ehandle) return MB_FAILURE;
+          // 4b. Get the connectivity of the element
+        rval = mb->get_connectivity(&ehandle, 1, connect); // get the connectivity, in canonical order
+        if (MB_SUCCESS != rval) return rval;
+          // 4c. Get the coordinates of the vertices comprising that element
+        rval = mb->get_coords(connect.data(), connect.size(), coords.data()); // get the coordinates of those vertices
+        if (MB_SUCCESS != rval) return rval;
+      }
+    }
+  }
+
+    // 5. Release the structured mesh interface and destroy the MOAB instance
+  mb->release_interface(scdiface); // tell MOAB we're done with the ScdInterface
+  delete mb;
+  
+  return 0;
+}

This diff is so big that we needed to truncate the remainder.

https://bitbucket.org/fathomteam/moab/commits/a2b3c0e1d508/
Changeset:   a2b3c0e1d508
Branch:      None
User:        tautges
Date:        2013-05-07 22:05:16
Summary:     Work on cleaning up element evaluations and getting the tests of that to work, and
starting on spatial locator and tree testing.

Element evaluation:
- for tets, change the reverse evaluation strategy: changed to 25 iterations, and start from
  nearest vertex
- fixed a bug in original reverse evaluation implementation
- added an inside function that returns whether a given parameter is inside the element; for some elements
  (i.e. tets), there isn't necessarily a fixed upper value for all parameters
- fixed handling reverse evaluation function to allow particular element types to substitute their own evaluator
  function (and use this for tet evaluation)
- spectral quad, hex: use inside function instead of duplicating code to directly evaluate it
- in elem_eval_test, for integration test, create a tag with value 1 on vertices to compute volume;
  also fixed bugs in iteration over multiple elements

Spatial locator/trees:
- changed delete_tree to reset_tree
- enabled some things for structured mesh that weren't before
- added test/spatial_locator_test.cpp
- in SpatialLocator, add code to initialize tree if one isn't input

Other:
- in ScdInterface, if applications don't input coordinates, compute them from parametric space
- fixed some compile warnings in MBZoltan

Affected #:  30 files

diff --git a/src/AdaptiveKDTree.cpp b/src/AdaptiveKDTree.cpp
index 8b8f100..64dd994 100644
--- a/src/AdaptiveKDTree.cpp
+++ b/src/AdaptiveKDTree.cpp
@@ -63,7 +63,7 @@ namespace moab {
         return;
 
       if (myRoot) {
-        delete_tree();
+        reset_tree();
         myRoot = 0;
       }
     }
@@ -178,7 +178,7 @@ namespace moab {
         }
       }
   
-      delete_tree( *tree_root_set );
+      reset_tree( *tree_root_set );
 
       treeStats.reset();
       
@@ -221,8 +221,10 @@ namespace moab {
                                               MB_TAG_CREAT|storage,
                                               default_val );
 
-      if (MB_SUCCESS == rval) 
-        created_tags.push_back( tag_handle );
+      if (MB_SUCCESS == rval) {
+        if (std::find(created_tags.begin(), created_tags.end(), tag_handle) == created_tags.end())
+          created_tags.push_back( tag_handle );
+      }
       else {
         while( !created_tags.empty() ) {
           iface->tag_delete( created_tags.back() );
@@ -342,7 +344,7 @@ namespace moab {
       return MB_SUCCESS;
     }
 
-    ErrorCode AdaptiveKDTree::delete_tree( EntityHandle root_handle )
+    ErrorCode AdaptiveKDTree::reset_tree( EntityHandle root_handle )
     {
       ErrorCode rval;
 
@@ -917,9 +919,10 @@ namespace moab {
       }
   
         // non-polyhedron elements
+      std::vector<EntityHandle> dum_vector;
       for (i = elem_begin; i != poly_begin; ++i) {
         tool->tree_stats().leaf_object_tests()++;
-        rval = moab->get_connectivity( *i, conn, count, true );
+        rval = moab->get_connectivity( *i, conn, count, true, &dum_vector);
         if (MB_SUCCESS != rval) 
           return rval;
         if (count > (int)(sizeof(coords)/sizeof(coords[0])))

diff --git a/src/LocalDiscretization/ElemEvaluator.cpp b/src/LocalDiscretization/ElemEvaluator.cpp
index 8d836d9..1bf054f 100644
--- a/src/LocalDiscretization/ElemEvaluator.cpp
+++ b/src/LocalDiscretization/ElemEvaluator.cpp
@@ -14,7 +14,7 @@
 //#include "moab/SpectralHex.hpp"
 
 namespace moab { 
-    ErrorCode EvalSet::evaluate_reverse(EvalFcn eval, JacobianFcn jacob,
+    ErrorCode EvalSet::evaluate_reverse(EvalFcn eval, JacobianFcn jacob, InsideFcn inside_f,
                                         const double *posn, const double *verts, const int nverts, 
                                         const int ndim, const double tol, double *work, 
                                         double *params, bool *inside) {
@@ -26,7 +26,7 @@ namespace moab {
       const CartVect *cvposn = reinterpret_cast<const CartVect*>(posn);
 
         // initialize to center of element
-      *cvparams = CartVect(0.0);
+      *cvparams = CartVect(-.4);
   
       CartVect new_pos;
         // evaluate that first guess to get a new position
@@ -40,15 +40,16 @@ namespace moab {
       int iters=0;
         // while |res| larger than tol
       while (res % res > error_tol_sqr) {
-        if(++iters>10)
+        if(++iters>25)
           return MB_FAILURE;
 
           // get jacobian at current params
         rval = (*jacob)(cvparams->array(), verts, nverts, ndim, work, J[0]);
-        assert(J.determinant() > std::numeric_limits<double>::epsilon());
+        double det = J.determinant();
+        assert(det > std::numeric_limits<double>::epsilon());
 
           // new params tries to eliminate residual
-        *cvparams -= J.inverse() * res;
+        *cvparams -= J.inverse(1.0/det) * res;
 
           // get the new forward-evaluated position, and its difference from the target pt
         rval = (*eval)(params, verts, ndim, ndim, work, new_pos.array());
@@ -56,14 +57,21 @@ namespace moab {
         res = new_pos - *cvposn;
       }
 
-      if (inside && (*cvparams)[0] >= -1.0 && (*cvparams)[0] <= 1.0 &&
-          (*cvparams)[1] >= -1.0 && (*cvparams)[1] <= 1.0 &&
-          (*cvparams)[2] >= -1.0 && (*cvparams)[2] <= 1.0)
-        *inside = true;
+      if (inside)
+        *inside = (*inside_f)(params, ndim, tol);
 
       return MB_SUCCESS;
     }// Map::evaluate_reverse()
 
+    bool EvalSet::inside_function(const double *params, const int ndims, const double tol) 
+    {
+      if (params[0] >= -1-tol && params[0] <= 1+tol &&
+          (ndims < 2 || (params[1] >= -1-tol && params[1] <= 1+tol)) &&
+          (ndims < 3 || (params[2] >= -1-tol && params[2] <= 1+tol))) 
+        return true;
+      else return false;
+    }
+
         /** \brief Given type & #vertices, get an appropriate eval set */
     ErrorCode EvalSet::get_eval_set(EntityType tp, unsigned int num_vertices, EvalSet &eval_set) 
     {

diff --git a/src/LocalDiscretization/LinearHex.cpp b/src/LocalDiscretization/LinearHex.cpp
index b85b4bb..20e5229 100644
--- a/src/LocalDiscretization/LinearHex.cpp
+++ b/src/LocalDiscretization/LinearHex.cpp
@@ -94,11 +94,17 @@ namespace moab
       return MB_SUCCESS;
     }// LinearHex::integrate_vector()
 
-    ErrorCode LinearHex::reverseEvalFcn(const double *posn, const double *verts, const int nverts, const int ndim,
+    ErrorCode LinearHex::reverseEvalFcn(EvalFcn eval, JacobianFcn jacob, InsideFcn ins, 
+                                        const double *posn, const double *verts, const int nverts, const int ndim,
                                         const double tol, double *work, double *params, bool *is_inside) 
     {
       assert(posn && verts);
-      return EvalSet::evaluate_reverse(evalFcn, jacobianFcn, posn, verts, nverts, ndim, tol, work, params, is_inside);
+      return EvalSet::evaluate_reverse(eval, jacob, ins, posn, verts, nverts, ndim, tol, work, params, is_inside);
+    }
+
+    bool LinearHex::insideFcn(const double *params, const int ndim, const double tol) 
+    {
+      return EvalSet::inside_function(params, ndim, tol);
     }
     
 } // namespace moab

diff --git a/src/LocalDiscretization/LinearQuad.cpp b/src/LocalDiscretization/LinearQuad.cpp
index 88fab7e..ddd4918 100644
--- a/src/LocalDiscretization/LinearQuad.cpp
+++ b/src/LocalDiscretization/LinearQuad.cpp
@@ -73,10 +73,16 @@ namespace moab
       return MB_SUCCESS;
     } // LinearHex::integrate_vector()
 
-    ErrorCode LinearQuad::reverseEvalFcn(const double *posn, const double *verts, const int nverts, const int ndim,
+    ErrorCode LinearQuad::reverseEvalFcn(EvalFcn eval, JacobianFcn jacob, InsideFcn ins, 
+                                         const double *posn, const double *verts, const int nverts, const int ndim,
                                          const double tol, double *work, double *params, bool *is_inside) 
     {
-      return EvalSet::evaluate_reverse(evalFcn, jacobianFcn, posn, verts, nverts, ndim, tol, work, params, is_inside);
+      return EvalSet::evaluate_reverse(eval, jacob, ins, posn, verts, nverts, ndim, tol, work, params, is_inside);
     } 
 
+    bool LinearQuad::insideFcn(const double *params, const int ndim, const double tol) 
+    {
+      return EvalSet::inside_function(params, ndim, tol);
+    }
+    
 } // namespace moab

diff --git a/src/LocalDiscretization/LinearTet.cpp b/src/LocalDiscretization/LinearTet.cpp
index 544cbd9..2bff33e 100644
--- a/src/LocalDiscretization/LinearTet.cpp
+++ b/src/LocalDiscretization/LinearTet.cpp
@@ -38,10 +38,12 @@ namespace moab
       std::vector<double> f0(num_tuples);
       std::copy(field, field+num_tuples, f0.begin());
       std::copy(field, field+num_tuples, result);
-
+      
+      
       for (unsigned i = 1; i < 4; ++i) {
+        double p = 0.5*(params[i-1] + 1); // transform from -1 <= p <= 1 to 0 <= p <= 1
         for (int j = 0; j < num_tuples; j++)
-          result[j] += (field[i*num_tuples+j]-f0[j])*params[i-1];
+          result[j] += (field[i*num_tuples+j]-f0[j])*p;
       }
 
       return MB_SUCCESS;
@@ -71,11 +73,75 @@ namespace moab
       return MB_SUCCESS;
     }
     
-    ErrorCode LinearTet::reverseEvalFcn(const double *posn, const double *verts, const int nverts, const int ndim,
+    ErrorCode LinearTet::reverseEvalFcn(EvalFcn eval, JacobianFcn jacob, InsideFcn ins, 
+                                        const double *posn, const double *verts, const int nverts, const int ndim,
                                         const double tol, double *work, double *params, bool *is_inside) 
     {
       assert(posn && verts);
-      return EvalSet::evaluate_reverse(evalFcn, jacobianFcn, posn, verts, nverts, ndim, tol, work, params, is_inside);
+      return evaluate_reverse(eval, jacob, ins, posn, verts, nverts, ndim, tol, work, params, is_inside);
     } 
 
+    bool LinearTet::insideFcn(const double *params, const int , const double tol) 
+    {
+      return (params[0] >= -1.0-tol && params[1] >= -1.0-tol && params[2] >= -1.0-tol && 
+              params[0] + params[1] + params[2] <= -1.0+tol);
+      
+    }
+    
+    ErrorCode LinearTet::evaluate_reverse(EvalFcn eval, JacobianFcn jacob, InsideFcn inside_f,
+                                          const double *posn, const double *verts, const int nverts, 
+                                          const int ndim, const double tol, double *work, 
+                                          double *params, bool *inside) {
+        // TODO: should differentiate between epsilons used for
+        // Newton Raphson iteration, and epsilons used for curved boundary geometry errors
+        // right now, fix the tolerance used for NR
+      const double error_tol_sqr = tol*tol;
+      CartVect *cvparams = reinterpret_cast<CartVect*>(params);
+      const CartVect *cvposn = reinterpret_cast<const CartVect*>(posn);
+
+        // find best initial guess to improve convergence
+      CartVect tmp_params[] = {CartVect(-1,-1,-1), CartVect(1,-1,-1), CartVect(-1,1,-1), CartVect(-1,-1,1)};
+      double resl = HUGE;
+      CartVect new_pos, tmp_pos;
+      ErrorCode rval;
+      for (unsigned int i = 0; i < 4; i++) {
+        rval = (*eval)(tmp_params[i].array(), verts, ndim, ndim, work, tmp_pos.array());
+        if (MB_SUCCESS != rval) return rval;
+        double tmp_resl = (tmp_pos-*cvposn).length_squared();
+        if (tmp_resl < resl) {
+          *cvparams = tmp_params[i];
+          new_pos = tmp_pos;
+          resl = tmp_resl;
+        }        
+      }
+
+        // residual is diff between old and new pos; need to minimize that
+      CartVect res = new_pos - *cvposn;
+      Matrix3 J;
+      rval = (*jacob)(cvparams->array(), verts, nverts, ndim, work, J[0]);
+      double det = J.determinant();
+      assert(det > std::numeric_limits<double>::epsilon());
+      Matrix3 Ji = J.inverse(1.0/det);
+
+      int iters=0;
+        // while |res| larger than tol
+      while (res % res > error_tol_sqr) {
+        if(++iters>25)
+          return MB_FAILURE;
+
+          // new params tries to eliminate residual
+        *cvparams -= Ji * res;
+
+          // get the new forward-evaluated position, and its difference from the target pt
+        rval = (*eval)(params, verts, ndim, ndim, work, new_pos.array());
+        if (MB_SUCCESS != rval) return rval;
+        res = new_pos - *cvposn;
+      }
+
+      if (inside)
+        *inside = (*inside_f)(params, ndim, tol);
+
+      return MB_SUCCESS;
+    }// Map::evaluate_reverse()
+
 } // namespace moab

diff --git a/src/LocalDiscretization/QuadraticHex.cpp b/src/LocalDiscretization/QuadraticHex.cpp
index e55930e..ca4758b 100644
--- a/src/LocalDiscretization/QuadraticHex.cpp
+++ b/src/LocalDiscretization/QuadraticHex.cpp
@@ -105,11 +105,16 @@ namespace moab
       return MB_NOT_IMPLEMENTED;
     }
 
-    ErrorCode QuadraticHex::reverseEvalFcn(const double *posn, const double *verts, const int nverts, const int ndim,
+    ErrorCode QuadraticHex::reverseEvalFcn(EvalFcn eval, JacobianFcn jacob, InsideFcn ins, 
+                                           const double *posn, const double *verts, const int nverts, const int ndim,
                                            const double tol, double *work, double *params, bool *is_inside) 
     {
       assert(posn && verts);
-      return EvalSet::evaluate_reverse(evalFcn, jacobianFcn, posn, verts, nverts, ndim, tol, work, params, is_inside);
+      return EvalSet::evaluate_reverse(eval, jacob, ins, posn, verts, nverts, ndim, tol, work, params, is_inside);
     } 
 
+    bool QuadraticHex::insideFcn(const double *params, const int ndim, const double tol) 
+    {
+      return EvalSet::inside_function(params, ndim, tol);
+    }
 } // namespace moab

diff --git a/src/LocalDiscretization/SpectralHex.cpp b/src/LocalDiscretization/SpectralHex.cpp
index dc636c9..0e40eba 100644
--- a/src/LocalDiscretization/SpectralHex.cpp
+++ b/src/LocalDiscretization/SpectralHex.cpp
@@ -178,14 +178,11 @@ void SpectralHex::integrate_vector(const double *field_values, int num_tuples, d
   }
     //std::cout << "volume: " << volume << "\n";
 }
-  // this is the same as a linear hex, although we should not need it
-bool SpectralHex::is_inside(const CartVect & params, double tol) const
-{
-    // just look at the box+tol here
-  return ( params[0]>=-1.-tol) && (params[0]<=1.+tol) &&
-      ( params[1]>=-1.-tol) && (params[1]<=1.+tol) &&
-      ( params[2]>=-1.-tol) && (params[2]<=1.+tol);
-}
+
+    bool SpectralHex::insideFcn(const double *params, const int ndim, const double tol) 
+    {
+      return EvalSet::inside(params, ndim, tol);
+    }
 
   // SpectralHex
 

diff --git a/src/LocalDiscretization/SpectralQuad.cpp b/src/LocalDiscretization/SpectralQuad.cpp
index 681a5c7..cbd1251 100644
--- a/src/LocalDiscretization/SpectralQuad.cpp
+++ b/src/LocalDiscretization/SpectralQuad.cpp
@@ -114,7 +114,7 @@ bool SpectralQuad::reverseEvalFcn(const double *posn, const double *verts, const
     //copy parametric coords back
   params = r;
 
-  return is_inside(params, tol);
+  return insideFcn(params, 2, tol);
 }
 
 
@@ -145,13 +145,12 @@ void SpectralQuad:: integrate_vector(const double *field, const double *verts, c
 {
     // not implemented
 }
-  // this is the same as a linear hex, although we should not need it
-bool SpectralQuad::is_inside(const CartVect & params, double tol) const
-{
-    // just look at the box+tol here
-  return ( params[0]>=-1.-tol) && (params[0]<=1.+tol) &&
-      ( params[1]>=-1.-tol) && (params[1]<=1.+tol) ;
-}
+
+    bool SpectralQuad::insideFcn(const double *params, const int ndim, const double tol) 
+    {
+      return EvalSet::inside(params, ndim, tol);
+    }
+
   // something we don't do for spectral hex; we do it here because
   //       we do not store the position of gl points in a tag yet
 void SpectralQuad::compute_gl_positions()

diff --git a/src/LocalDiscretization/moab/ElemEvaluator.hpp b/src/LocalDiscretization/moab/ElemEvaluator.hpp
index 161bfc5..d7d87a7 100644
--- a/src/LocalDiscretization/moab/ElemEvaluator.hpp
+++ b/src/LocalDiscretization/moab/ElemEvaluator.hpp
@@ -1,21 +1,18 @@
 #ifndef ELEM_EVALUATOR_HPP
 #define ELEM_EVALUATOR_HPP
 
-#include <vector>
-
 #include "moab/Interface.hpp"
 #include "moab/CartVect.hpp"
 #include "moab/Matrix3.hpp"
 #include "moab/CN.hpp"
 
+#include <vector>
+
 namespace moab {
 
     typedef ErrorCode (*EvalFcn)(const double *params, const double *field, const int ndim, const int num_tuples, 
                           double *work, double *result);
 
-    typedef ErrorCode (*ReverseEvalFcn)(const double *posn, const double *verts, const int nverts, const int ndim,
-                                         const double tol, double *work, double *params, bool *is_inside);
-        
     typedef ErrorCode (*JacobianFcn)(const double *params, const double *verts, const int nverts, const int ndim, 
                                      double *work, double *result);
         
@@ -24,6 +21,12 @@ namespace moab {
 
     typedef ErrorCode (*InitFcn)(const double *verts, const int nverts, double *&work);
 
+    typedef bool (*InsideFcn)(const double *verts, const int ndims, const double tol);
+
+    typedef ErrorCode (*ReverseEvalFcn)(EvalFcn eval, JacobianFcn jacob, InsideFcn ins, 
+                                        const double *posn, const double *verts, const int nverts, const int ndim,
+                                        const double tol, double *work, double *params, bool *is_inside);
+        
     class EvalSet
     {
   public:
@@ -42,12 +45,15 @@ namespace moab {
         /** \brief Initialization function for an element */
       InitFcn initFcn;
 
+        /** \brief Function that returns whether or not the parameters are inside the natural space of the element */
+      InsideFcn insideFcn;
+
         /** \brief Bare constructor */
-      EvalSet() : evalFcn(NULL), reverseEvalFcn(NULL), jacobianFcn(NULL), integrateFcn(NULL), initFcn(NULL) {}
+      EvalSet() : evalFcn(NULL), reverseEvalFcn(NULL), jacobianFcn(NULL), integrateFcn(NULL), initFcn(NULL), insideFcn(NULL) {}
 
         /** \brief Constructor */
-      EvalSet(EvalFcn eval, ReverseEvalFcn rev, JacobianFcn jacob, IntegrateFcn integ, InitFcn initf)
-              : evalFcn(eval), reverseEvalFcn(rev), jacobianFcn(jacob), integrateFcn(integ), initFcn(initf)
+      EvalSet(EvalFcn eval, ReverseEvalFcn rev, JacobianFcn jacob, IntegrateFcn integ, InitFcn initf, InsideFcn insidef)
+              : evalFcn(eval), reverseEvalFcn(rev), jacobianFcn(jacob), integrateFcn(integ), initFcn(initf), insideFcn(insidef)
           {}
 
         /** \brief Given an entity handle, get an appropriate eval set, based on type & #vertices */
@@ -63,14 +69,17 @@ namespace moab {
         jacobianFcn = eval.jacobianFcn;
         integrateFcn = eval.integrateFcn;
         initFcn = eval.initFcn;
+        insideFcn = eval.insideFcn;
         return *this;
       }
 
-      static ErrorCode evaluate_reverse(EvalFcn eval, JacobianFcn jacob,
+        /** \brief Common function to do reverse evaluation based on evaluation and jacobian functions */
+      static ErrorCode evaluate_reverse(EvalFcn eval, JacobianFcn jacob, InsideFcn inside_f,
                                         const double *posn, const double *verts, const int nverts, 
                                         const int ndim, const double tol, double *work, double *params, 
                                         bool *inside);
-      
+        /** \brief Common function that returns true if params is in [-1,1]^ndims */
+      static bool inside_function(const double *params, const int ndims, const double tol);
     };
 
         /** \brief Given an entity handle, get an appropriate eval set, based on type & #vertices */
@@ -145,7 +154,7 @@ namespace moab {
          * \param params Parameters at which to query the element
          * \param tol Tolerance, usually 10^-6 or so
          */
-      bool is_inside(const double *params, double tol) const;
+      bool inside(const double *params, const double tol) const;
 
         /** \brief Set the eval set for a given type entity
          * \param tp Entity type for which to set the eval set
@@ -291,6 +300,7 @@ namespace moab {
         numTuples = 3;
         tagDim = 0;
         tagHandle = 0;
+        if (numVerts) tagSpace.resize(numVerts*sizeof(double));
         return rval;
       }
       else if (tagHandle != tag) {
@@ -387,9 +397,9 @@ namespace moab {
     inline ErrorCode ElemEvaluator::reverse_eval(const double *posn, const double tol, double *params, bool *ins) const
     {
       assert(entHandle && MBMAXTYPE != entType);
-      return EvalSet::evaluate_reverse(evalSets[entType].evalFcn, evalSets[entType].jacobianFcn, 
-                                       posn, vertPos[0].array(), numVerts, entDim, tol, workSpace, 
-                                       params, ins);
+      return (*evalSets[entType].reverseEvalFcn)(evalSets[entType].evalFcn, evalSets[entType].jacobianFcn, evalSets[entType].insideFcn,
+                                                 posn, vertPos[0].array(), numVerts, entDim, tol, workSpace, 
+                                                 params, ins);
     }
         
       /** \brief Evaluate the jacobian of the cached entity at a given parametric location */
@@ -414,6 +424,11 @@ namespace moab {
                                                workSpace, result);
     }
 
+    inline bool ElemEvaluator::inside(const double *params, const double tol) const 
+    {
+      return (*evalSets[entType].insideFcn)(params, entDim, tol);
+    }
+
     inline ErrorCode ElemEvaluator::set_eval_set(EntityHandle eh) 
     {
       EvalSet eset;

diff --git a/src/LocalDiscretization/moab/LinearHex.hpp b/src/LocalDiscretization/moab/LinearHex.hpp
index 358899e..e7ca3f4 100644
--- a/src/LocalDiscretization/moab/LinearHex.hpp
+++ b/src/LocalDiscretization/moab/LinearHex.hpp
@@ -15,7 +15,8 @@ public:
                            double *work, double *result);
         
     /** \brief Reverse-evaluation of parametric coordinates at physical space position */
-  static ErrorCode reverseEvalFcn(const double *posn, const double *verts, const int nverts, const int ndim,
+  static ErrorCode reverseEvalFcn(EvalFcn eval, JacobianFcn jacob, InsideFcn ins, 
+                                  const double *posn, const double *verts, const int nverts, const int ndim,
                                   const double tol, double *work, double *params, bool *is_inside);
         
     /** \brief Evaluate the jacobian at a specified parametric position */
@@ -26,9 +27,12 @@ public:
   static ErrorCode integrateFcn(const double *field, const double *verts, const int nverts, const int ndim, const int num_tuples, 
                                 double *work, double *result);
 
+        /** \brief Function that returns whether or not the parameters are inside the natural space of the element */
+  static bool insideFcn(const double *params, const int ndim, const double tol);
+  
   static EvalSet eval_set() 
       {
-        return EvalSet(evalFcn, reverseEvalFcn, jacobianFcn, integrateFcn, (InitFcn)NULL);
+        return EvalSet(evalFcn, reverseEvalFcn, jacobianFcn, integrateFcn, (InitFcn)NULL, insideFcn);
       }
       
   static bool compatible(EntityType tp, int numv, EvalSet &eset) 

diff --git a/src/LocalDiscretization/moab/LinearQuad.hpp b/src/LocalDiscretization/moab/LinearQuad.hpp
index b1c2ca8..26882a1 100644
--- a/src/LocalDiscretization/moab/LinearQuad.hpp
+++ b/src/LocalDiscretization/moab/LinearQuad.hpp
@@ -15,9 +15,10 @@ public:
                            double *work, double *result);
         
     /** \brief Reverse-evaluation of parametric coordinates at physical space position */
-  static ErrorCode reverseEvalFcn(const double *posn, const double *verts, const int nverts, const int ndim,
+  static ErrorCode reverseEvalFcn(EvalFcn eval, JacobianFcn jacob, InsideFcn ins, 
+                                  const double *posn, const double *verts, const int nverts, const int ndim,
                                   const double tol, double *work, double *params, bool *is_inside);
-        
+
     /** \brief Evaluate the jacobian at a specified parametric position */
   static ErrorCode jacobianFcn(const double *params, const double *verts, const int nverts, const int ndim, 
                                double *work, double *result);
@@ -26,9 +27,12 @@ public:
   static ErrorCode integrateFcn(const double *field, const double *verts, const int nverts, const int ndim, const int num_tuples, 
                                 double *work, double *result);
 
+        /** \brief Function that returns whether or not the parameters are inside the natural space of the element */
+  static bool insideFcn(const double *params, const int ndim, const double tol);
+  
   static EvalSet eval_set() 
       {
-        return EvalSet(evalFcn, reverseEvalFcn, jacobianFcn, integrateFcn, NULL);
+        return EvalSet(evalFcn, reverseEvalFcn, jacobianFcn, integrateFcn, NULL, insideFcn);
       }
 
   static bool compatible(EntityType tp, int numv, EvalSet &eset) 

diff --git a/src/LocalDiscretization/moab/LinearTet.hpp b/src/LocalDiscretization/moab/LinearTet.hpp
index c355c1b..464b1f6 100644
--- a/src/LocalDiscretization/moab/LinearTet.hpp
+++ b/src/LocalDiscretization/moab/LinearTet.hpp
@@ -15,7 +15,8 @@ public:
                            double *work, double *result);
         
     /** \brief Reverse-evaluation of parametric coordinates at physical space position */
-  static ErrorCode reverseEvalFcn(const double *posn, const double *verts, const int nverts, const int ndim,
+  static ErrorCode reverseEvalFcn(EvalFcn eval, JacobianFcn jacob, InsideFcn ins, 
+                                  const double *posn, const double *verts, const int nverts, const int ndim,
                                   const double tol, double *work, double *params, bool *is_inside);
         
     /** \brief Evaluate the jacobian at a specified parametric position */
@@ -29,9 +30,17 @@ public:
     /** \brief Initialize this EvalSet */
   static ErrorCode initFcn(const double *verts, const int nverts, double *&work);
       
+        /** \brief Function that returns whether or not the parameters are inside the natural space of the element */
+  static bool insideFcn(const double *params, const int ndim, const double tol);
+  
+  static ErrorCode evaluate_reverse(EvalFcn eval, JacobianFcn jacob, InsideFcn inside_f,
+                                    const double *posn, const double *verts, const int nverts, 
+                                    const int ndim, const double tol, double *work, 
+                                    double *params, bool *inside);
+
   static EvalSet eval_set() 
       {
-        return EvalSet(evalFcn, reverseEvalFcn, jacobianFcn, integrateFcn, initFcn);
+        return EvalSet(evalFcn, reverseEvalFcn, jacobianFcn, integrateFcn, initFcn, insideFcn);
       }
       
   static bool compatible(EntityType tp, int numv, EvalSet &eset) 

diff --git a/src/LocalDiscretization/moab/QuadraticHex.hpp b/src/LocalDiscretization/moab/QuadraticHex.hpp
index 9fcbdd8..0801ad7 100644
--- a/src/LocalDiscretization/moab/QuadraticHex.hpp
+++ b/src/LocalDiscretization/moab/QuadraticHex.hpp
@@ -15,7 +15,8 @@ public:
                            double *work, double *result);
         
     /** \brief Reverse-evaluation of parametric coordinates at physical space position */
-  static ErrorCode reverseEvalFcn(const double *posn, const double *verts, const int nverts, const int ndim,
+  static ErrorCode reverseEvalFcn(EvalFcn eval, JacobianFcn jacob, InsideFcn ins, 
+                                  const double *posn, const double *verts, const int nverts, const int ndim,
                                   const double tol, double *work, double *params, bool *is_inside);
         
     /** \brief Evaluate the jacobian at a specified parametric position */
@@ -26,9 +27,12 @@ public:
   static ErrorCode integrateFcn(const double *field, const double *verts, const int nverts, const int ndim, const int num_tuples, 
                                 double *work, double *result);
 
+        /** \brief Function that returns whether or not the parameters are inside the natural space of the element */
+  static bool insideFcn(const double *params, const int ndim, const double tol);
+  
   static EvalSet eval_set() 
       {
-        return EvalSet(evalFcn, reverseEvalFcn, jacobianFcn, integrateFcn, NULL);
+        return EvalSet(evalFcn, reverseEvalFcn, jacobianFcn, integrateFcn, NULL, insideFcn);
       }
       
   static bool compatible(EntityType tp, int numv, EvalSet &eset) 

diff --git a/src/LocalDiscretization/moab/SpectralHex.hpp b/src/LocalDiscretization/moab/SpectralHex.hpp
index e9d7005..e6464c3 100644
--- a/src/LocalDiscretization/moab/SpectralHex.hpp
+++ b/src/LocalDiscretization/moab/SpectralHex.hpp
@@ -17,8 +17,9 @@ public:
                            double *work, double *result);
         
     /** \brief Reverse-evaluation of parametric coordinates at physical space position */
-  static ErrorCode reverseEvalFcn(const double *posn, const double *verts, const int nverts, const int ndim,
-                                  double tol, double *work, double *params, bool *is_inside);
+  static ErrorCode reverseEvalFcn(EvalFcn eval, JacobianFcn jacob, InsideFcn ins, 
+                                  const double *posn, const double *verts, const int nverts, const int ndim,
+                                  const double tol, double *work, double *params, bool *is_inside);
         
     /** \brief Evaluate the jacobian at a specified parametric position */
   static ErrorCode jacobianFcn(const double *params, const double *verts, const int nverts, const int ndim, 
@@ -31,6 +32,9 @@ public:
     /** \brief Initialize this EvalSet */
   static ErrorCode initFcn(const double *verts, const int nverts, double *&work);
       
+        /** \brief Function that returns whether or not the parameters are inside the natural space of the element */
+  static bool insideFcn(const double *params, const int ndim, const double tol);
+  
   static EvalSet eval_set() 
       {
         return EvalSet(evalFcn, reverseEvalFcn, jacobianFcn, integrateFcn, initFcn);

diff --git a/src/LocalDiscretization/moab/SpectralQuad.hpp b/src/LocalDiscretization/moab/SpectralQuad.hpp
index b56e84c..8716a43 100644
--- a/src/LocalDiscretization/moab/SpectralQuad.hpp
+++ b/src/LocalDiscretization/moab/SpectralQuad.hpp
@@ -17,7 +17,8 @@ public:
                            double *work, double *result);
         
     /** \brief Reverse-evaluation of parametric coordinates at physical space position */
-  static ErrorCode reverseEvalFcn(const double *posn, const double *verts, const int nverts, const int ndim,
+  static ErrorCode reverseEvalFcn(EvalFcn eval, JacobianFcn jacob, InsideFcn ins, 
+                                  const double *posn, const double *verts, const int nverts, const int ndim,
                                   const double tol, double *work, double *params, bool *is_inside);
         
     /** \brief Evaluate the jacobian at a specified parametric position */
@@ -30,6 +31,9 @@ public:
     /** \brief Initialize this EvalSet */
   static ErrorCode initFcn(const double *verts, const int nverts, double *&work);
       
+        /** \brief Function that returns whether or not the parameters are inside the natural space of the element */
+  static bool insideFcn(const double *params, const int ndim, const double tol);
+  
   static EvalSet eval_set() 
       {
         return EvalSet(evalFcn, reverseEvalFcn, jacobianFcn, integrateFcn, initFcn);

diff --git a/src/ScdInterface.cpp b/src/ScdInterface.cpp
index e2b18bb..24e62c3 100644
--- a/src/ScdInterface.cpp
+++ b/src/ScdInterface.cpp
@@ -113,12 +113,12 @@ ErrorCode ScdInterface::construct_box(HomCoord low, HomCoord high, const double
   rval = create_scd_sequence(low, high, MBVERTEX, 0, new_box);
   ERRORR(rval, "Trouble creating scd vertex sequence.");
 
-  if (num_coords && coords) {
-      // set the vertex coordinates
-    double *xc, *yc, *zc;
-    rval = new_box->get_coordinate_arrays(xc, yc, zc);
-    ERRORR(rval, "Couldn't get vertex coordinate arrays.");
+    // set the vertex coordinates
+  double *xc, *yc, *zc;
+  rval = new_box->get_coordinate_arrays(xc, yc, zc);
+  ERRORR(rval, "Couldn't get vertex coordinate arrays.");
 
+  if (coords && num_coords) {
     unsigned int i = 0;
     for (int kl = low[2]; kl <= high[2]; kl++) {
       for (int jl = low[1]; jl <= high[1]; jl++) {
@@ -133,6 +133,23 @@ ErrorCode ScdInterface::construct_box(HomCoord low, HomCoord high, const double
       }
     }
   }
+  else {
+    unsigned int i = 0;
+    for (int kl = low[2]; kl <= high[2]; kl++) {
+      for (int jl = low[1]; jl <= high[1]; jl++) {
+        for (int il = low[0]; il <= high[0]; il++) {
+          xc[i] = (double) il;
+          if (new_box->box_size()[1])
+            yc[i] = (double) jl;
+          else yc[i] = 0.0;
+          if (new_box->box_size()[2])
+            zc[i] = (double) kl;
+          else zc[i] = 0.0;
+          i++;
+        }
+      }
+    }
+  }
 
     // create element sequence
   SequenceManager *seq_mgr = mbImpl->sequence_manager();

diff --git a/src/SpatialLocator.cpp b/src/SpatialLocator.cpp
index 7848b95..70b0aec 100644
--- a/src/SpatialLocator.cpp
+++ b/src/SpatialLocator.cpp
@@ -1,14 +1,23 @@
 #include "moab/SpatialLocator.hpp"
 #include "moab/Interface.hpp"
 #include "moab/ElemEvaluator.hpp"
+#include "moab/AdaptiveKDTree.hpp"
 
 namespace moab 
 {
 
     SpatialLocator::SpatialLocator(Interface *impl, Range &elems, Tree *tree, ElemEvaluator *eval) 
-            : mbImpl(impl), myElems(elems), myDim(-1), myTree(tree), elemEval(eval)
+            : mbImpl(impl), myElems(elems), myDim(-1), myTree(tree), elemEval(eval), iCreatedTree(false)
     {
-      if (!elems.empty()) myDim = mbImpl->dimension_from_handle(*elems.rbegin());
+      if (!myTree) {
+        myTree = new AdaptiveKDTree(impl);
+        iCreatedTree = true;
+      }
+      if (!elems.empty()) {
+        myDim = mbImpl->dimension_from_handle(*elems.rbegin());
+        ErrorCode rval = myTree->build_tree(myElems);
+        if (MB_SUCCESS != rval) throw rval;
+      }
     }
 
     ErrorCode SpatialLocator::add_elems(Range &elems) 
@@ -72,6 +81,7 @@ namespace moab
         if (!elemEval) {
           ents[i] = closest_leaf;
           params[i3] = params[i3+1] = params[i3+2] = -2;
+          if (is_inside && closest_leaf) is_inside[i] = true;
           continue;
         }
     
@@ -85,7 +95,7 @@ namespace moab
         bool tmp_inside;
         for(Range::iterator rit = range_leaf.begin(); rit != range_leaf.end(); rit++)
         {
-          bool *is_ptr = (is_inside ? is_inside+i3 : &tmp_inside);      
+          bool *is_ptr = (is_inside ? is_inside+i : &tmp_inside);      
           rval = elemEval->set_ent_handle(*rit); 
           if (MB_SUCCESS != rval) return rval;
           rval = elemEval->reverse_eval(pos+i3, 0.0, params+i3, is_ptr);

diff --git a/src/Tree.cpp b/src/Tree.cpp
index b7cd7ee..54df1a3 100644
--- a/src/Tree.cpp
+++ b/src/Tree.cpp
@@ -76,8 +76,9 @@ namespace moab
 
         // elements with vertex-handle connectivity list
       const Range::const_iterator poly_begin = elems.lower_bound( MBPOLYHEDRON, elem_begin );
+      std::vector<EntityHandle> dum_vector;
       for (i = elem_begin; i != poly_begin; ++i) {
-        rval = iface.get_connectivity( *i, conn, len, true );
+        rval = iface.get_connectivity( *i, conn, len, true, &dum_vector);
         if (MB_SUCCESS != rval)
           return rval;
 

diff --git a/src/moab/AdaptiveKDTree.hpp b/src/moab/AdaptiveKDTree.hpp
index d16a69d..a2afea9 100644
--- a/src/moab/AdaptiveKDTree.hpp
+++ b/src/moab/AdaptiveKDTree.hpp
@@ -55,8 +55,8 @@ namespace moab {
                                    EntityHandle *tree_root_set = NULL,
                                    FileOptions *options = NULL);
 
-        //! Destroy the tree, optionally checking we have the right root
-      ErrorCode delete_tree(EntityHandle root_handle = 0);
+        //! Reset the tree, optionally checking we have the right root
+      virtual ErrorCode reset_tree(EntityHandle root_handle = 0);
 
         /** \brief Get leaf containing input position.
          *

diff --git a/src/moab/SpatialLocator.hpp b/src/moab/SpatialLocator.hpp
index bc5be70..907a133 100644
--- a/src/moab/SpatialLocator.hpp
+++ b/src/moab/SpatialLocator.hpp
@@ -26,7 +26,7 @@ namespace moab {
       SpatialLocator(Interface *impl, Range &elems, Tree *tree = NULL, ElemEvaluator *eval = NULL);
 
         /* destructor */
-      virtual ~SpatialLocator() {}
+      virtual ~SpatialLocator();
 
         /* add elements to be searched */
       ErrorCode add_elems(Range &elems);
@@ -41,17 +41,14 @@ namespace moab {
                               bool *is_inside = NULL);
       
         /* locate a point */
-      ErrorCode locate_point(const CartVect &pos, 
-                             EntityHandle &ent, CartVect &params, 
-                             double rel_tol = 0.0, double abs_tol = 0.0,
-                             bool *is_inside = NULL);
-
-        /* locate a point */
       ErrorCode locate_point(const double *pos, 
                              EntityHandle &ent, double *params, 
                              double rel_tol = 0.0, double abs_tol = 0.0,
                              bool *is_inside = NULL);
 
+        /* return the tree */
+      Tree *get_tree() {return myTree;}
+      
   private:
 
         /* MOAB instance */
@@ -68,21 +65,20 @@ namespace moab {
       
         /* element evaluator */
       ElemEvaluator *elemEval;
-      
+
+        /* whether I created the tree or not (determines whether to delete it or not on destruction) */
+      bool iCreatedTree;
     };
 
-    ErrorCode SpatialLocator::locate_point(const CartVect &pos, 
-                                           EntityHandle &ent, CartVect &params, 
-                                           double rel_tol, double abs_tol,
-                                           bool *is_inside) 
+    inline SpatialLocator::~SpatialLocator() 
     {
-      return locate_points((double*)(&pos), 1, &ent, (double*)(&params), rel_tol, abs_tol, is_inside);
+      if (iCreatedTree && myTree) delete myTree;
     }
-
-    ErrorCode SpatialLocator::locate_point(const double *pos, 
-                                           EntityHandle &ent, double *params, 
-                                           double rel_tol, double abs_tol,
-                                           bool *is_inside) 
+    
+    inline ErrorCode SpatialLocator::locate_point(const double *pos, 
+                                                  EntityHandle &ent, double *params, 
+                                                  double rel_tol, double abs_tol,
+                                                  bool *is_inside) 
     {
       return locate_points(pos, 1, &ent, params, rel_tol, abs_tol, is_inside);
     }

diff --git a/src/moab/Tree.hpp b/src/moab/Tree.hpp
index 7a6a9d2..4fc3735 100644
--- a/src/moab/Tree.hpp
+++ b/src/moab/Tree.hpp
@@ -44,6 +44,11 @@ namespace moab {
          */
       virtual ~Tree();
 
+        /** \brief Destroy the tree maintained by this object, optionally checking we have the right root.
+         * \param root If non-NULL, check that this is the root, return failure if not
+         */
+      virtual ErrorCode reset_tree(EntityHandle root = 0) = 0;
+
         /** Build the tree
          * Build a tree with the entities input.  If a non-NULL tree_root_set pointer is input, 
          * use the pointed-to set as the root of this tree (*tree_root_set!=0) otherwise construct 
@@ -65,11 +70,6 @@ namespace moab {
                                    EntityHandle *tree_root_set = NULL,
                                    FileOptions *options = NULL) = 0;
 
-        /** \brief Destroy the tree maintained by this object, optionally checking we have the right root.
-         * \param root If non-NULL, check that this is the root, return failure if not
-         */
-      virtual ErrorCode delete_tree(EntityHandle root = 0) = 0;
-
         /** \brief Get bounding box for entire tree
          * If no tree has been built yet, returns 3*0 for all dimensions.
          * \param box_min Minimum corner of box

diff --git a/test/Makefile.am b/test/Makefile.am
index e452e42..27a8baa 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -45,7 +45,8 @@ TESTS = range_test \
 	reorder_test \
 	test_prog_opt \
 	coords_connect_iterate \
-	elem_eval_test
+	elem_eval_test \
+	spatial_locator_test
 
 if HDF5_FILE
   TESTS += mbfacet_test \
@@ -118,6 +119,7 @@ var_len_test_no_template_SOURCES = $(var_len_test_SOURCES)
 var_len_test_no_template_CPPFLAGS = -UTEMPLATE_SPECIALIZATION $(AM_CPPFLAGS) $(CPPFLAGS)
 
 tag_test_SOURCES = TestUtil.hpp TagTest.cpp
+spatial_locator_test_SOURCES = TestUtil.hpp spatial_locator_test.cpp
 
 mbcn_test_SOURCES = $(top_srcdir)/src/moab/CN.hpp \
                     $(top_srcdir)/src/CN.cpp \

diff --git a/test/adaptive_kd_tree_tests.cpp b/test/adaptive_kd_tree_tests.cpp
index 17e112f..c744474 100644
--- a/test/adaptive_kd_tree_tests.cpp
+++ b/test/adaptive_kd_tree_tests.cpp
@@ -549,7 +549,7 @@ void leaf_iterator_test()
   rval = iter.step();
   CHECK( MB_SUCCESS != rval );
 
-  rval = tool.delete_tree( root );
+  rval = tool.reset_tree( root );
   CHECK( MB_SUCCESS == rval );
   root = 0;
   
@@ -743,21 +743,21 @@ void test_build_tree_bisect_triangles( )
   rval = tool.build_tree( box_tris, &root, &opts);
   CHECK( MB_SUCCESS == rval );
   test_valid_tree( &tool, root, opts, box_tris );
-  tool.delete_tree(root);
+  tool.reset_tree(root);
   
   moab.delete_mesh(); box_tris.clear();
   build_triangle_octahedron( &moab, box_tris );
   rval = tool.build_tree( box_tris, &root, &opts );
   CHECK( MB_SUCCESS == rval );
   test_valid_tree( &tool, root, opts, box_tris );
-  tool.delete_tree(root);
+  tool.reset_tree(root);
   
   moab.delete_mesh(); box_tris.clear();
   build_triangle_box_large( &moab, box_tris );
   rval = tool.build_tree( box_tris, &root, &opts );
   CHECK( MB_SUCCESS == rval );
   test_valid_tree( &tool, root, opts, box_tris );
-  tool.delete_tree(root);
+  tool.reset_tree(root);
   
   options << "MAX_DEPTH=2;";
   opts = FileOptions(options.str().c_str());
@@ -765,7 +765,7 @@ void test_build_tree_bisect_triangles( )
   rval = tool.build_tree( box_tris, &root, &opts );
   CHECK( MB_SUCCESS == rval );
   test_valid_tree( &tool, root, opts, box_tris );
-  tool.delete_tree(root);
+  tool.reset_tree(root);
 }
   
 void test_closest_triangle()
@@ -838,7 +838,7 @@ void test_closest_triangle()
   }
   
     // now do it all again with a lot more triangles
-  tool.delete_tree(root);
+  tool.reset_tree(root);
   moab.delete_mesh(); box_tris.clear();
 
   build_triangle_box_large( &moab, box_tris );
@@ -934,7 +934,7 @@ void test_sphere_intersect_triangles()
   
     // now do it all again with a lot more triangles
 
-  tool.delete_tree(root);
+  tool.reset_tree(root);
   moab.delete_mesh(); box_tris.clear();
   build_triangle_box_large( &moab, box_tris );
 

diff --git a/test/elem_eval_test.cpp b/test/elem_eval_test.cpp
index cd4c8a8..850099d 100644
--- a/test/elem_eval_test.cpp
+++ b/test/elem_eval_test.cpp
@@ -40,7 +40,7 @@ CartVect hex_verts[] = {
     CartVect( 0, 0, 0 )
 };
 
-const double EPS1 = 1e-6;
+double EPS1;
 
 void test_eval(ElemEvaluator &ee, bool test_integrate) 
 {
@@ -55,9 +55,13 @@ void test_eval(ElemEvaluator &ee, bool test_integrate)
       for (params[2] = -1; params[2] <= 1; params[2] += 0.2) {
 
           // forward/reverse evaluation should get back to the same point, within tol
+        if (!ee.inside(params.array(), EPS1)) continue;
+        
         rval = ee.eval(params.array(), posn.array()); CHECK_ERR(rval);
         rval = ee.reverse_eval(posn.array(), EPS1, params2.array(), &is_inside); CHECK_ERR(rval);
-        CHECK_REAL_EQUAL(0.0, (params - params2).length(), EPS1);
+        if ((params - params2).length() > 3*EPS1) 
+          std::cerr << params << std::endl;
+        CHECK_REAL_EQUAL(0.0, (params - params2).length(), 3*EPS1);
 
           // jacobian should be >= 0
         rval = ee.jacobian(params.array(), jacob.array()); CHECK_ERR(rval);
@@ -67,35 +71,44 @@ void test_eval(ElemEvaluator &ee, bool test_integrate)
     }
   }
 
+  if (!test_integrate) return;
+  
     // tag equal to coordinates should integrate to avg position, since volume is 1
   Tag tag;
+    // make a temporary tag and set it on vertices to the vertex positions
   rval = ee.get_moab()->tag_get_handle(NULL, 3, MB_TYPE_DOUBLE, tag, MB_TAG_DENSE | MB_TAG_CREAT); CHECK_ERR(rval);
   rval = ee.get_moab()->tag_set_data(tag, ee.get_vert_handles(), ee.get_num_verts(), hex_verts[0].array()); CHECK_ERR(rval);
-  
+    // set that temporary tag on the evaluator so that's what gets integrated
   rval = ee.set_tag_handle(tag, 0); CHECK_ERR(rval);
 
-  if (test_integrate) {
-    CartVect integral, avg(0.0);
-    rval = ee.integrate(integral.array()); CHECK_ERR(rval);
-    CHECK_REAL_EQUAL(0.0, (avg - integral).length(), EPS1);
-  }
-  
+  CartVect integral, avg(0.0);
+  rval = ee.integrate(integral.array()); CHECK_ERR(rval);
+  CHECK_REAL_EQUAL(0.0, (avg - integral).length(), EPS1);
+
+    // delete the temporary tag
+  rval = ee.get_moab()->tag_delete(tag);
+  CHECK_ERR(rval);
+    // set the ee's tag back to coords
+  rval = ee.set_tag_handle(0, 0); CHECK_ERR(rval);
 }
 
-void test_evals(ElemEvaluator &ee, bool test_integrate, EntityHandle *starth, int num_ents, double total_vol) 
+void test_evals(ElemEvaluator &ee, bool test_integrate, EntityHandle *ents, int num_ents, Tag onetag, double total_vol) 
 {
-  for (int i = 0; i < num_ents; i++)
+  for (int i = 0; i < num_ents; i++) {
+    ee.set_ent_handle(ents[i]);
     test_eval(ee, false);
+  }
     
   if (!test_integrate) return;
-  if (!num_ents || !starth) CHECK_ERR(MB_FAILURE);
+  if (!num_ents || !ents) CHECK_ERR(MB_FAILURE);
 
+  ErrorCode rval = ee.set_tag_handle(onetag, 0); CHECK_ERR(rval);
+  
   double tot_vol = 0.0;
-  EntityHandle eh = *starth;
   for (int i = 0; i < num_ents; i++) {
     double tmp_vol;
-    ee.set_ent_handle(eh++);
-    ErrorCode rval = ee.integrate(&tmp_vol); CHECK_ERR(rval);
+    ee.set_ent_handle(ents[i]);
+    rval = ee.integrate(&tmp_vol); CHECK_ERR(rval);
     tot_vol += tmp_vol;
   }
   CHECK_REAL_EQUAL(total_vol, tot_vol, EPS1);
@@ -126,6 +139,7 @@ void test_linear_hex()
   ee.set_tag_handle(0, 0);
   ee.set_eval_set(MBHEX, LinearHex::eval_set());
 
+  EPS1 = 1e-6;
   test_eval(ee, true);
 }
 
@@ -143,13 +157,14 @@ void test_quadratic_hex()
   ee.set_tag_handle(0, 0);
   ee.set_eval_set(MBHEX, QuadraticHex::eval_set());
 
+  EPS1 = 1e-6;
   test_eval(ee, false);
 }
 
 void test_linear_tet() 
 {
   Core mb;
-  Range verts, tets;
+  Range verts;
   ErrorCode rval = mb.create_vertices((double*)hex_verts[0].array(), 8, verts); CHECK_ERR(rval);
   EntityHandle starth = 1, *conn;
   int conn_inds[] = {1, 6, 4, 5,    1, 4, 6, 3,    0, 1, 3, 4,    1, 2, 3, 6,    3, 4, 6, 7};
@@ -157,10 +172,18 @@ void test_linear_tet()
   rval = mb.query_interface(ru); CHECK_ERR(rval);
   rval = ru->get_element_connect(5, 4, MBTET, 1, starth, conn); CHECK_ERR(rval);
   for (unsigned int i = 0; i < 20; i++) conn[i] = verts[conn_inds[i]];
-  
-  ElemEvaluator ee(&mb, starth, 0);
+  EntityHandle tets[5];
+  for (unsigned int i = 0; i < 5; i++) tets[i] = starth + i;
+  ElemEvaluator ee(&mb, 0, 0);
   ee.set_tag_handle(0, 0);
   ee.set_eval_set(MBTET, LinearTet::eval_set());
 
-  test_evals(ee, true, &starth, 5, 8.0);
+    // make a tag whose value is one on all vertices
+  Tag tag;
+  rval = mb.tag_get_handle(NULL, 1, MB_TYPE_DOUBLE, tag, MB_TAG_DENSE | MB_TAG_CREAT); CHECK_ERR(rval);
+  std::vector<double> vals(verts.size(), 1.0);
+  rval = mb.tag_set_data(tag, verts, &vals[0]); CHECK_ERR(rval);
+
+  EPS1 = 1e-6;
+  test_evals(ee, true, tets, 5, tag, 8.0);
 }

diff --git a/test/kd_tree_test.cpp b/test/kd_tree_test.cpp
index 3eeb76f..379fd1b 100644
--- a/test/kd_tree_test.cpp
+++ b/test/kd_tree_test.cpp
@@ -257,7 +257,7 @@ void test_tree_delete()
   Tag data;
   const EntityHandle root = create_tree( tool, DEPTH, INTERVALS, &data );
   
-  err = tool.delete_tree( root );
+  err = tool.reset_tree( root );
   CHECK_ERR(err);
   
   Range ents;

diff --git a/test/kd_tree_tool.cpp b/test/kd_tree_tool.cpp
index 5fc85bc..190c805 100644
--- a/test/kd_tree_tool.cpp
+++ b/test/kd_tree_tool.cpp
@@ -303,7 +303,7 @@ void delete_existing_tree( Interface* interface )
   if (!trees.empty())
     std::cout << "Destroying existing tree(s) contained in file" << std::endl;
   for (Range::iterator i = trees.begin(); i != trees.end(); ++i)
-    tool.delete_tree( *i );
+    tool.reset_tree( *i );
   
   trees.clear();
   tool.find_all_trees( trees );

diff --git a/test/spatial_locator_test.cpp b/test/spatial_locator_test.cpp
new file mode 100644
index 0000000..5b1617c
--- /dev/null
+++ b/test/spatial_locator_test.cpp
@@ -0,0 +1,91 @@
+#include "moab/Core.hpp"
+#include "moab/SpatialLocator.hpp"
+#include "moab/Tree.hpp"
+#include "moab/HomXform.hpp"
+#include "moab/ScdInterface.hpp"
+#include "moab/CartVect.hpp"
+
+#ifdef USE_MPI
+#include "moab_mpi.h"
+#endif
+
+#include "TestUtil.hpp"
+
+#include <cstdlib>
+
+using namespace moab;
+
+const int npoints = 1000;
+
+void test_just_tree();
+ErrorCode create_hex_mesh(Interface &mb, Range &elems, int n = 10, int dim = 3);
+
+int main(int argc, char **argv)
+{
+#ifdef USE_MPI
+  int fail = MPI_Init(&argc, &argv);
+  if (fail) return fail;
+#else
+  // silence the warning of parameters not used, in serial; there should be a smarter way :(
+  argv[0]=argv[argc-argc];
+#endif
+
+  RUN_TEST(test_just_tree);
+  
+#ifdef USE_MPI
+  fail = MPI_Finalize();
+  if (fail) return fail;
+#endif
+
+  return 0;
+}
+
+void test_just_tree() 
+{
+  ErrorCode rval;
+  Core mb;
+  
+    // create a simple mesh to test
+  Range elems;
+  rval = create_hex_mesh(mb, elems); CHECK_ERR(rval);
+
+    // initialize spatial locator with the elements and the default tree type
+  SpatialLocator *sl = new SpatialLocator(&mb, elems);
+  CartVect box_min, box_max, box_del, test_pt, test_res;
+  rval = sl->get_bounding_box(box_min, box_max); CHECK_ERR(rval);
+  box_del = box_max - box_min;
+
+  double denom = 1.0 / (double)RAND_MAX;
+  bool is_in;
+  EntityHandle ent;
+  for (int i = 0; i < npoints; i++) {    
+      // generate a small number of random point to test
+    double rx = (double)rand() * denom, ry = (double)rand() * denom, rz = (double)rand() * denom;
+    test_pt = box_min + CartVect(rx*box_del[0], ry*box_del[1], rz*box_del[2]);
+
+    // call spatial locator to locate points
+    rval = sl->locate_points(test_pt.array(), 1, &ent, test_res.array(), 0.0, 0.0, &is_in); CHECK_ERR(rval);
+
+    // verify that the point was found
+    CHECK_EQUAL(is_in, true);
+  }
+
+    // destroy spatial locator, and tree along with it
+  delete sl;
+}
+
+ErrorCode create_hex_mesh(Interface &mb, Range &elems, int n, int dim) 
+{
+  ScdInterface *scdi;
+  ErrorCode rval = mb.query_interface(scdi); CHECK_ERR(rval);
+  HomCoord high(n-1, -1, -1);
+  if (dim > 1) high[1] = n-1;
+  if (dim > 2) high[2] = n-1;
+  ScdBox *new_box;
+  rval = scdi->construct_box(HomCoord(0, 0, 0), high, NULL, 0, new_box); CHECK_ERR(rval);
+  rval = mb.release_interface(scdi); CHECK_ERR(rval);
+
+  rval = mb.get_entities_by_dimension(0, dim, elems); CHECK_ERR(rval);
+
+  return rval;
+}

diff --git a/tools/mbcoupler/ElemUtil.cpp b/tools/mbcoupler/ElemUtil.cpp
index 80ade78..82e7200 100644
--- a/tools/mbcoupler/ElemUtil.cpp
+++ b/tools/mbcoupler/ElemUtil.cpp
@@ -434,17 +434,6 @@ namespace Element {
         this->vertex = v;
       }
 
-
-  inline const std::vector<CartVect>& Map::get_vertices() {
-    return this->vertex;
-  }
-  //
-  void Map::set_vertices(const std::vector<CartVect>& v) {
-    if(v.size() != this->vertex.size()) {
-      throw ArgError();
-    }
-    this->vertex = v;
-  }// Map::set_vertices()
   //
   CartVect Map::ievaluate(const CartVect& x, double tol, const CartVect& x0) const {
     // TODO: should differentiate between epsilons used for
@@ -496,30 +485,6 @@ namespace Element {
     return x;
   }// LinearEdge::evaluate
 
-// filescope for static member data that is cached
-  const double LinearEdge::corner[2][3] = {  { -1, 0, 0 },
-                                         {  1, 0, 0 } };
-
-  LinearEdge::LinearEdge() : Map(0) {
-
-  }// LinearEdge::LinearEdge()
-
-  /* For each point, its weight and location are stored as an array.
-     Hence, the inner dimension is 2, the outer dimension is gauss_count.
-     We use a one-point Gaussian quadrature, since it integrates linear functions exactly.
-  */
-  const double LinearEdge::gauss[1][2] = { {  2.0,           0.0          } };
-
-  CartVect LinearEdge::evaluate( const CartVect& xi ) const {
-    CartVect x(0.0);
-    for (unsigned i = 0; i < LinearEdge::corner_count; ++i) {
-      const double N_i = (1.0 + xi[0]*corner[i][0]);
-      x += N_i * this->vertex[i];
-    }
-    x /= LinearEdge::corner_count;
-    return x;
-  }// LinearEdge::evaluate
-
   Matrix3 LinearEdge::jacobian( const CartVect& xi ) const {
     Matrix3 J(0.0);
     for (unsigned i = 0; i < LinearEdge::corner_count; ++i) {

diff --git a/tools/mbcoupler/ElemUtilTest.cpp b/tools/mbcoupler/ElemUtilTest.cpp
index eae57c2..cb6fb15 100644
--- a/tools/mbcoupler/ElemUtilTest.cpp
+++ b/tools/mbcoupler/ElemUtilTest.cpp
@@ -158,3 +158,34 @@ void test_hex_nat_coords()
 //std::cout << std::endl;
 }
   
+void test_tet_nat_coords()
+{
+  CartVect xi, result_xi;
+  bool valid;
+  // rename EPS to EPS1 because of conflict with definition of EPS in types.h
+  // types.h is now included in the header.
+  const double EPS1 = 1e-6;
+  
+    // first test with cube because it's easier to debug failures
+  std::vector<CartVect> tet_corners;
+  tet_corners.push_back(hex_corners[1]);
+  tet_corners.push_back(hex_corners[6]);
+  tet_corners.push_back(hex_corners[4]);
+  tet_corners.push_back(hex_corners[5]);
+  
+  Element::LinearTet tet(tet_corners);
+  for (xi[0] = -1; xi[0] <= 1; xi[0] += 0.2) {
+    for (xi[1] = -1; xi[1] <= 1; xi[1] += 0.2) {
+      for (xi[2] = -1; xi[2] <= 1; xi[2] += 0.2) {
+        const CartVect pt = hex_map(xi, cube_corners);
+        result_xi = hex.ievaluate(pt, EPS1/10);
+        double dum = EPS1/10;
+        valid = hex.inside_nat_space(result_xi, dum);
+        CHECK(valid);
+        CHECK_REAL_EQUAL( xi[0], result_xi[0], EPS1 );
+        CHECK_REAL_EQUAL( xi[1], result_xi[1], EPS1 );
+        CHECK_REAL_EQUAL( xi[2], result_xi[2], EPS1 );
+      }
+    }
+  }
+}

diff --git a/tools/mbzoltan/MBZoltan.cpp b/tools/mbzoltan/MBZoltan.cpp
index e72c97e..087a74c 100644
--- a/tools/mbzoltan/MBZoltan.cpp
+++ b/tools/mbzoltan/MBZoltan.cpp
@@ -211,7 +211,7 @@ ErrorCode MBZoltan::balance_mesh(const char *zmethod,
                    exportProcs, &assignment);
 
   if (mbpc->proc_config().proc_rank() == 0) {
-    ErrorCode result = write_partition(mbpc->proc_config().proc_size(), elems, assignment,
+    result = write_partition(mbpc->proc_config().proc_size(), elems, assignment,
                                        write_as_sets, write_as_tags);
 
     if (MB_SUCCESS != result) return result;
@@ -1357,14 +1357,14 @@ ErrorCode MBZoltan::write_partition(const int nparts,
 
       // check for empty sets, warn if there are any
     Range empty_sets;
-    for (Range::iterator rit = partSets.begin(); rit != partSets.end(); rit++) {
+    for (rit = partSets.begin(); rit != partSets.end(); rit++) {
       int num_ents = 0;
       result = mbImpl->get_number_entities_by_handle(*rit, num_ents);
       if (MB_SUCCESS != result || !num_ents) empty_sets.insert(*rit);
     }
     if (!empty_sets.empty()) {
       std::cout << "WARNING: " << empty_sets.size() << " empty sets in partition: ";
-      for (Range::iterator rit = empty_sets.begin(); rit != empty_sets.end(); rit++)
+      for (rit = empty_sets.begin(); rit != empty_sets.end(); rit++)
         std::cout << *rit << " ";
       std::cout << std::endl;
     }


https://bitbucket.org/fathomteam/moab/commits/cfcb79070dcc/
Changeset:   cfcb79070dcc
Branch:      None
User:        tautges
Date:        2013-05-07 22:06:18
Summary:     Merged fathomteam/moab into master
Affected #:  19 files

diff --git a/config/compiler.m4 b/config/compiler.m4
index ce00d10..18df411 100644
--- a/config/compiler.m4
+++ b/config/compiler.m4
@@ -126,6 +126,8 @@ fi
 if test "xno" != "x$CHECK_FC"; then
   AC_PROG_FC
   AC_PROG_F77
+  AC_F77_LIBRARY_LDFLAGS
+  AC_FC_LIBRARY_LDFLAGS
 fi
 
 ]) # FATHOM_CHECK_COMPILERS

diff --git a/configure.ac b/configure.ac
index b6fdaa9..5669a14 100644
--- a/configure.ac
+++ b/configure.ac
@@ -67,6 +67,14 @@ if test "xyes" = "x$ENABLE_FORTRAN" && test "x" != "x$FC"; then
   AC_FC_WRAPPERS
 fi
 
+if test "xyes" = "x$ENABLE_FORTRAN" && test "x" != "x$FLIBS"; then
+   LIBS="$LIBS $FLIBS"
+fi
+
+if test "xyes" = "x$ENABLE_FORTRAN" && test "x" != "x$FCLIBS"; then
+   LIBS="$LIBS $FCLIBS"
+fi
+
 ################################################################################
 #                           Check for need for extra flags to support cray pointers
 ################################################################################
@@ -1163,6 +1171,8 @@ AC_SUBST([EXPORT_LTFLAGS])
 AC_SUBST([EXPORT_LDFLAGS])
 AC_SUBST([AM_CXXFLAGS])
 AC_SUBST([AM_CFLAGS])
+  AC_SUBST([AM_FCFLAGS])
+  AC_SUBST([AM_FFLAGS])
 AC_SUBST([DISTCHECK_CONFIGURE_FLAGS])
 
 AC_ARG_VAR([FC], [FORTRAN compiler command])

diff --git a/examples/DirectAccessNoHoles.cpp b/examples/DirectAccessNoHoles.cpp
index 445c517..340efae 100644
--- a/examples/DirectAccessNoHoles.cpp
+++ b/examples/DirectAccessNoHoles.cpp
@@ -1,31 +1,30 @@
-/** @example DirectAccess.cpp \n
+/** @example DirectAccessNoHoles.cpp \n
  * \brief Use direct access to MOAB data to avoid calling through API \n
  *
- * This example creates a 1d row of quad elements, with a user-specified number of "holes" (missing quads) in the row:
+ * This example creates a 1d row of quad elements, such that all quad and vertex handles
+ * are contiguous in the handle space and in the database.  Then it shows how to get access
+ * to pointers to MOAB-native data for vertex coordinates, quad connectivity, tag storage,
+ * and vertex to quad adjacency lists.  This allows applications to access this data directly
+ * without going through MOAB's API.  In cases where the mesh is not changing (or only mesh
+ * vertices are moving), this can save significant execution time in applications.
  *
- *  ----------------------      ----------------------      --------
- *  |      |      |      |      |      |      |      |      |      |       
- *  |      |      |      |(hole)|      |      |      |(hole)|      | ...
- *  |      |      |      |      |      |      |      |      |      |
- *  ----------------------      ----------------------      --------
- *
- * This makes (nholes+1) contiguous runs of quad handles in the handle space
- * This example shows how to use the xxx_iterate functions in MOAB (xxx = coords, connect, tag, adjacencies) to get 
- * direct pointer access to MOAB internal storage, which can be used without calling through the MOAB API.
+ *  ----------------------
+ *  |      |      |      |       
+ *  |      |      |      | ...
+ *  |      |      |      |
+ *  ----------------------
  *
  *    -#  Initialize MOAB \n
- *    -#  Create a quad mesh with holes, as depicted above
+ *    -#  Create a quad mesh, as depicted above
  *    -#  Create 2 dense tags (tag1, tag2) for avg position to assign to quads, and # verts per quad (tag3)
  *    -#  Get connectivity, coordinate, tag1 iterators
  *    -#  Iterate through quads, computing midpoint based on vertex positions, set on quad-based tag1
- *    -#  Set up map from starting quad handle for a chunk to struct of (tag1_ptr, tag2_ptr, tag3_ptr), pointers to
- *        the dense tag storage for those tags for the chunk
  *    -#  Iterate through vertices, summing positions into tag2 on connected quads and incrementing vertex count
  *    -#  Iterate through quads, normalizing tag2 by vertex count and comparing values of tag1 and tag2
  *
  * <b>To compile</b>: \n
- *    make DirectAccessWithHoles MOAB_DIR=<installdir>  \n
- * <b>To run</b>: ./DirectAccess [-nquads <# quads>] [-holes <# holes>]\n
+ *    make DirectAccessNoHoles MOAB_DIR=<installdir>  \n
+ * <b>To run</b>: ./DirectAccessNoHoles [-nquads <# quads>]\n
  *
  */
 
@@ -131,12 +130,16 @@ int main(int argc, char **argv)
         
     // Normalize tag2 by vertex count (tag3); loop over elements using same approach as before
     // At the same time, compare values of tag1 and tag2
+  int n_dis = 0;
   for (Range::iterator q_it = quads.begin(); q_it != quads.end(); q_it++) {
     int i = *q_it - start_quad;
     for (int j = 0; j < 3; j++) tag2_ptr[3*i+j] /= (double)tag3_ptr[i];  // normalize by # verts
-    if (tag1_ptr[3*i] != tag2_ptr[3*i] || tag1_ptr[3*i+1] != tag2_ptr[3*i+1] || tag1_ptr[3*i+2] != tag2_ptr[3*i+2]) 
+    if (tag1_ptr[3*i] != tag2_ptr[3*i] || tag1_ptr[3*i+1] != tag2_ptr[3*i+1] || tag1_ptr[3*i+2] != tag2_ptr[3*i+2]) {
       std::cout << "Tag1, tag2 disagree for element " << *q_it + i << std::endl;
+      n_dis++;
+    }
   }
+  if (!n_dis) std::cout << "All tags agree, success!" << std::endl;
 
     // Ok, we're done, shut down MOAB
   delete mbImpl;
@@ -151,7 +154,7 @@ ErrorCode create_mesh_no_holes(Interface *mbImpl, int nquads)
   ErrorCode rval = mbImpl->query_interface(read_iface); CHKERR(rval, "query_interface");
   std::vector<double *> coords;
   EntityHandle start_vert, start_elem, *connect;
-    // create verts, num is 4(nquads+1) because they're in a 1d row; will initialize coords in loop over quads later
+    // create verts, num is 2(nquads+1) because they're in a 1d row; will initialize coords in loop over quads later
   rval = read_iface->get_node_coords (3, 2*(nquads+1), 0, start_vert, coords); CHKERR(rval, "get_node_arrays");
     // create quads
   rval = read_iface->get_element_connect(nquads, 4, MBQUAD, 0, start_elem, connect); CHKERR(rval, "get_element_connect");
@@ -160,8 +163,12 @@ ErrorCode create_mesh_no_holes(Interface *mbImpl, int nquads)
     coords[1][2*i] = 0.0; coords[1][2*i+1] = 1.0; // y coords
     coords[2][2*i] = coords[2][2*i+1] = (double) 0.0; // z values, all zero (2d mesh)
     EntityHandle quad_v = start_vert + 2*i;
-    for (int j = 0; j < 4; j++) connect[4*i+j] = quad_v+j; // connectivity of each quad is a sequence starting from quad_v
+    connect[4*i+0] = quad_v;
+    connect[4*i+1] = quad_v+2;
+    connect[4*i+2] = quad_v+3;
+    connect[4*i+3] = quad_v+1;
   }
+  
     // last two vertices
   coords[0][2*nquads] = coords[0][2*nquads+1] = (double) nquads;
   coords[1][2*nquads] = 0.0; coords[1][2*nquads+1] = 1.0; // y coords

diff --git a/examples/DirectAccessNoHolesF90.F90 b/examples/DirectAccessNoHolesF90.F90
new file mode 100644
index 0000000..3cf5fa7
--- /dev/null
+++ b/examples/DirectAccessNoHolesF90.F90
@@ -0,0 +1,231 @@
+! @example DirectAccessNoHolesF90.F90 \n
+! \brief Use direct access to MOAB data to avoid calling through API, in Fortran90 \n
+!
+! This example creates a 1d row of quad elements, such that all quad and vertex handles
+! are contiguous in the handle space and in the database.  Then it shows how to get access
+! to pointers to MOAB-native data for vertex coordinates, quad connectivity, and tag storage
+! (vertex to quad adjacency lists aren't accessible from Fortran because they are std::vector's).  
+! This allows applications to access this data directly
+! without going through MOAB's API.  In cases where the mesh is not changing (or only mesh
+! vertices are moving), this can save significant execution time in applications.
+!
+! Using direct access (or MOAB in general) from Fortran is complicated in two specific ways:
+! 1) There is no way to use arrays with specified dimension starting/ending values with ISO_C_BINDING;
+!    therefore, all arrays passed back from MOAB/iMesh must use 1-based indices; this makes it a bit
+!    more difficult to traverse the direct arrays.  In this example, I explicitly use indices that
+!    look like my_array(1+v_ind...) to remind users of this.
+! 2) Arithmetic on handles is complicated by the fact that Fortran has no unsigned integer type.  I get
+!    around this by assigning to a C-typed variable first, before the handle arithmetic.  This seems to
+!    work fine.  C-typed variables are part of the Fortran95 standard.
+!
+!  ----------------------
+!  |      |      |      |       
+!  |      |      |      | ...
+!  |      |      |      |
+!  ----------------------
+!
+!    -#  Initialize MOAB \n
+!    -#  Create a quad mesh, as depicted above
+!    -#  Create 2 dense tags (tag1, tag2) for avg position to assign to quads, and # verts per quad (tag3)
+!    -#  Get connectivity, coordinate, tag1 iterators
+!    -#  Iterate through quads, computing midpoint based on vertex positions, set on quad-based tag1
+!    -#  Iterate through vertices, summing positions into tag2 on connected quads and incrementing vertex count
+!    -#  Iterate through quads, normalizing tag2 by vertex count and comparing values of tag1 and tag2
+!
+! <b>To compile</b>: \n
+!    make DirectAccessNoHolesF90 MOAB_DIR=<installdir>  \n
+! <b>To run</b>: ./DirectAccessNoHolesF90 [-nquads <# quads>]\n
+!
+!
+
+#define CHECK(a) \
+  if (a .ne. iBase_SUCCESS) call exit(a)
+
+module freem
+  interface
+     subroutine c_free(ptr) bind(C, name='free')
+       use ISO_C_BINDING
+       type(C_ptr), value, intent(in) :: ptr
+     end subroutine c_free
+  end interface
+end module freem
+
+program DirectAccessNoHolesF90
+  use ISO_C_BINDING
+  use freem
+  implicit none
+#include "iMesh_f.h"
+
+  ! declarations
+  iMesh_Instance imesh
+  iBase_EntitySetHandle root_set
+  integer ierr, nquads, nquads_tmp, nverts
+  iBase_TagHandle tag1h, tag2h, tag3h
+  TYPE(C_PTR) verts_ptr, quads_ptr, conn_ptr, x_ptr, y_ptr, z_ptr, tag1_ptr, tag2_ptr, tag3_ptr, &
+       tmp_quads_ptr, offsets_ptr  ! pointers that are equivalence'd to arrays using c_f_pointer
+  real(C_DOUBLE), pointer :: x(:), y(:), z(:), tag1(:), tag2(:) ! arrays equivalence'd to pointers
+  integer, pointer :: tag3(:), offsets(:)                       ! arrays equivalence'd to pointers
+  iBase_EntityHandle, pointer :: quads(:), verts(:), conn(:), tmp_quads(:)  ! arrays equivalence'd to pointers
+  iBase_EntityArrIterator viter, qiter
+  integer(C_SIZE_T) :: startv, startq, v_ind, e_ind  ! needed to do handle arithmetic
+  integer count, vpere, e, i, j, v, offsets_size, tmp_quads_size, n_dis
+  character*120 opt
+
+  ! initialize interface and get root set
+  call iMesh_newMesh("", imesh, ierr); CHECK(ierr)
+  call iMesh_getRootSet(%VAL(imesh), root_set, ierr); CHECK(ierr)
+
+  ! create mesh
+  nquads_tmp = 1000
+  call create_mesh_no_holes(imesh, nquads_tmp, ierr); CHECK(ierr)
+
+  ! get all vertices and quads as arrays
+  nverts = 0
+  call iMesh_getEntities(%VAL(imesh), %VAL(root_set), %VAL(0), %VAL(iBase_VERTEX), &
+       verts_ptr, nverts, nverts, ierr); CHECK(ierr)
+  call c_f_pointer(verts_ptr, verts, [nverts])
+  nquads = 0
+  call iMesh_getEntities(%VAL(imesh), %VAL(root_set), %VAL(2), %VAL(iMesh_QUADRILATERAL), &
+       quads_ptr, nquads, nquads, ierr); CHECK(ierr)
+  call c_f_pointer(quads_ptr, quads, [nquads])
+
+  ! First vertex/quad is at start of vertex/quad list, and is offset for vertex/quad index calculation
+  startv = verts(1); startq = quads(1)
+  call c_free(quads_ptr)  ! free memory we allocated in MOAB
+
+  ! create tag1 (element-based avg), tag2 (vertex-based avg)
+  opt = 'moab:TAG_STORAGE_TYPE=DENSE moab:TAG_DEFAULT_VALUE=0'
+  call iMesh_createTagWithOptions(%VAL(imesh), 'tag1', opt, %VAL(3), %VAL(iBase_DOUBLE), &
+       tag1h, ierr, %VAL(4), %VAL(56)); CHECK(ierr)
+  call iMesh_createTagWithOptions(%VAL(imesh), 'tag2', opt, %VAL(3), %VAL(iBase_DOUBLE), &
+       tag2h, ierr, %VAL(4), %VAL(56)); CHECK(ierr)
+
+  ! Get iterator to verts, then pointer to coordinates
+  call iMesh_initEntArrIter(%VAL(imesh), %VAL(root_set), %VAL(iBase_VERTEX), %VAL(iMesh_ALL_TOPOLOGIES), &
+       %VAL(nverts), %VAL(0), viter, ierr); CHECK(ierr)
+  call iMesh_coordsIterate(%VAL(imesh), %VAL(viter), x_ptr, y_ptr, z_ptr, count, ierr); CHECK(ierr)
+  CHECK(count-nverts) ! check that all verts are in one contiguous chunk
+  call c_f_pointer(x_ptr, x, [nverts]); call c_f_pointer(y_ptr, y, [nverts]); call c_f_pointer(z_ptr, z, [nverts])
+
+  ! Get iterator to quads, then pointers to connectivity and tags
+  call iMesh_initEntArrIter(%VAL(imesh), %VAL(root_set), %VAL(iBase_FACE), %VAL(iMesh_ALL_TOPOLOGIES), &
+       %VAL(nquads), %VAL(0), qiter, ierr); CHECK(ierr)
+  call iMesh_connectIterate(%VAL(imesh), %VAL(qiter), conn_ptr, vpere, count, ierr); CHECK(ierr)
+  call c_f_pointer(conn_ptr, conn, [vpere*nquads])
+  call iMesh_tagIterate(%VAL(imesh), %VAL(tag1h), %VAL(qiter), tag1_ptr, count, ierr); CHECK(ierr)
+  call c_f_pointer(tag1_ptr, tag1, [3*nquads])
+  call iMesh_tagIterate(%VAL(imesh), %VAL(tag2h), %VAL(qiter), tag2_ptr, count, ierr); CHECK(ierr)
+  call c_f_pointer(tag2_ptr, tag2, [3*nquads])
+  
+  ! iterate over elements, computing tag1 from coords positions; use (1+... in array indices for 1-based indexing
+  do i = 0, nquads-1
+     tag1(1+3*i+0) = 0.0; tag1(1+3*i+1) = 0.0; tag1(1+3*i+2) = 0.0 ! initialize position for this element
+     do j = 0, vpere-1 ! loop over vertices in this quad
+        v_ind = conn(1+vpere*i+j) ! assign to v_ind to allow handle arithmetic
+        v_ind = v_ind - startv ! vert index is just the offset from start vertex
+        tag1(1+3*i+0) = tag1(1+3*i+0) + x(1+v_ind)
+        tag1(1+3*i+1) = tag1(1+3*i+1) + y(1+v_ind) ! sum vertex positions into tag1...
+        tag1(1+3*i+2) = tag1(1+3*i+2) + z(1+v_ind)
+     end do
+     tag1(1+3*i+0) = tag1(1+3*i+0) / vpere;
+     tag1(1+3*i+1) = tag1(1+3*i+1) / vpere; ! then normalize
+     tag1(1+3*i+2) = tag1(1+3*i+2) / vpere;
+  end do ! loop over elements in chunk
+    
+  ! Iterate through vertices, summing positions into tag2 on connected elements; get adjacencies all at once,
+  ! could also get them per vertex (time/memory tradeoff)
+  tmp_quads_size = 0
+  offsets_size = 0
+  call iMesh_getEntArrAdj(%VAL(imesh), verts, %VAL(nverts), %VAL(iMesh_QUADRILATERAL), &
+       tmp_quads_ptr, tmp_quads_size, tmp_quads_size, &
+       offsets_ptr, offsets_size, offsets_size, ierr); CHECK(ierr) 
+  call c_f_pointer(tmp_quads_ptr, tmp_quads, [tmp_quads_size])
+  call c_f_pointer(offsets_ptr, offsets, [offsets_size])
+  call c_free(verts_ptr)  ! free memory we allocated in MOAB
+  do v = 0, nverts-1
+     do e = 1+offsets(1+v), 1+offsets(1+v+1)-1  ! 1+ because offsets are in terms of 0-based arrays
+        e_ind = tmp_quads(e) ! assign to e_ind to allow handle arithmetic
+        e_ind = e_ind - startq ! e_ind is the quad handle minus the starting quad handle
+        tag2(1+3*e_ind+0) = tag2(1+3*e_ind+0) + x(1+v)
+        tag2(1+3*e_ind+1) = tag2(1+3*e_ind+1) + y(1+v)   ! tag on each element is 3 doubles, x/y/z
+        tag2(1+3*e_ind+2) = tag2(1+3*e_ind+2) + z(1+v)
+     end do
+  end do
+  call c_free(tmp_quads_ptr)  ! free memory we allocated in MOAB
+  call c_free(offsets_ptr)    ! free memory we allocated in MOAB
+
+  ! Normalize tag2 by vertex count (vpere); loop over elements using same approach as before
+  ! At the same time, compare values of tag1 and tag2
+  n_dis = 0
+  do e = 0, nquads-1
+     do j = 0, 2
+        tag2(1+3*e+j) = tag2(1+3*e+j) / vpere;  ! normalize by # verts
+     end do
+     if (tag1(1+3*e) .ne. tag2(1+3*e) .or. tag1(1+3*e+1) .ne. tag2(1+3*e+1) .or. tag1(1+3*e+2) .ne. tag2(1+3*i+2)) then
+        print *, "Tag1, tag2 disagree for element ", e
+        print *, "tag1: ", tag1(1+3*e), tag1(1+3*e+1), tag1(1+3*e+2)
+        print *, "tag2: ", tag2(1+3*e), tag2(1+3*e+1), tag2(1+3*e+2)
+        n_dis = n_dis + 1
+     end if
+  end do
+  if (n_dis .eq. 0) print *, 'All tags agree, success!'
+
+    ! Ok, we are done, shut down MOAB
+  call iMesh_dtor(%VAL(imesh), ierr)
+  return
+end program DirectAccessNoHolesF90
+
+subroutine create_mesh_no_holes(imesh, nquads, ierr) 
+  use ISO_C_BINDING
+  use freem
+  implicit none
+#include "iMesh_f.h"
+
+  iMesh_Instance imesh
+  integer nquads, ierr
+
+  real(C_DOUBLE), pointer :: coords(:,:)
+  TYPE(C_PTR) connect_ptr, tmp_ents_ptr, stat_ptr
+  iBase_EntityHandle, pointer :: connect(:), tmp_ents(:)
+  integer, pointer :: stat(:)
+  integer nverts, tmp_size, stat_size, i
+
+  ! first make the mesh, a 1d array of quads with left hand side x = elem_num; vertices are numbered in layers
+  ! create verts, num is 2(nquads+1) because they're in a 1d row
+  nverts = 2*(nquads+1)
+  allocate(coords(0:2, 0:nverts-1))
+  do i = 0, nquads-1
+     coords(0,2*i) = i; coords(0,2*i+1) = i ! x values are all i
+     coords(1,2*i) = 0.0; coords(1,2*i+1) = 1.0 ! y coords
+     coords(2,2*i) = 0.0; coords(2,2*i+1) = 0.0 ! z values, all zero (2d mesh)
+  end do
+  ! last two vertices
+  coords(0, nverts-2) = nquads; coords(0, nverts-1) = nquads
+  coords(1, nverts-2) = 0.0; coords(1, nverts-1) = 1.0 ! y coords
+  coords(2, nverts-2) = 0.0; coords(2, nverts-1) = 0.0 ! z values, all zero (2d mesh)
+  tmp_size = 0
+  call iMesh_createVtxArr(%VAL(imesh), %VAL(nverts), %VAL(iBase_INTERLEAVED), &
+       coords, %VAL(3*nverts), tmp_ents_ptr, tmp_size, tmp_size, ierr); CHECK(ierr)
+  call c_f_pointer(tmp_ents_ptr, tmp_ents, [nverts])
+  deallocate(coords)
+  allocate(connect(0:4*nquads-1))
+  do i = 0, nquads-1
+     connect(4*i+0) = tmp_ents(1+2*i)
+     connect(4*i+1) = tmp_ents(1+2*i+2)
+     connect(4*i+2) = tmp_ents(1+2*i+3)
+     connect(4*i+3) = tmp_ents(1+2*i+1)
+  end do
+  stat_size = 0
+  stat_ptr = C_NULL_PTR
+  ! re-use tmp_ents here; we know it'll always be larger than nquads so it's ok
+  call iMesh_createEntArr(%VAL(imesh), %VAL(iMesh_QUADRILATERAL), connect, %VAL(4*nquads), &
+       tmp_ents_ptr, tmp_size, tmp_size, stat_ptr, stat_size, stat_size, ierr); CHECK(ierr)
+
+  ierr = iBase_SUCCESS
+
+  call c_free(tmp_ents_ptr)
+  call c_free(stat_ptr)
+  deallocate(connect)
+
+  return
+end subroutine create_mesh_no_holes

diff --git a/examples/HelloMOAB.cpp b/examples/HelloMOAB.cpp
index ee81de9..ebab971 100644
--- a/examples/HelloMOAB.cpp
+++ b/examples/HelloMOAB.cpp
@@ -8,13 +8,15 @@
 
 
 #include "moab/Core.hpp"
+#include <iostream>
+#include <assert.h>
 
 using namespace moab;
 using namespace std;
 
 string test_file_name = string(MESH_DIR) + string("/3k-tri-sphere.vtk");
 
-int main( int argc, char** argv[] )
+int main( int argc, char** argv )
 {
   Interface *iface = new Core;
 
@@ -24,7 +26,7 @@ int main( int argc, char** argv[] )
     test_file_name = argv[1];
   }  
     //load the mesh from vtk file
-  ErrorCode rval = iface->load_mesh( test_file_name );
+  ErrorCode rval = iface->load_mesh( test_file_name.c_str() );
   assert( rval == MB_SUCCESS);
 
     //get verts entities

diff --git a/examples/makefile b/examples/makefile
index fd6585e..3402f96 100644
--- a/examples/makefile
+++ b/examples/makefile
@@ -1,7 +1,8 @@
 # MOAB_DIR points to top-level install dir, below which MOAB's lib/ and include/ are located
 include ${MOAB_DIR}/lib/moab.make
+include ${MOAB_DIR}/lib/iMesh-Defs.inc
 
-.SUFFIXES: .o .cpp
+.SUFFIXES: .o .cpp .F90
 
 # MESH_DIR is the top-level MOAB source directory, used to locate mesh files that come with MOAB source
 MESH_DIR="../MeshFiles/unittest"
@@ -27,6 +28,12 @@ DirectAccessWithHoles: DirectAccessWithHoles.o
 DirectAccessNoHoles: DirectAccessNoHoles.o
 	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK}
 
+DirectAccessNoHolesF90: DirectAccessNoHolesF90.o
+	${MOAB_CXX} -o $@ $< ${IMESH_LIBS}
+
 .cpp.o :
 	${MOAB_CXX} ${MOAB_CXXFLAGS} ${MOAB_INCLUDES} -DMESH_DIR=\"${MESH_DIR}\" -c $<
 
+.F90.o :
+	${IMESH_FC} ${IMESH_FCFLAGS} ${IMESH_INCLUDES} ${IMESH_FCDEFS} -DMESH_DIR=\"${MESH_DIR}\" -c $<
+

diff --git a/itaps/iBase_f.h.in b/itaps/iBase_f.h.in
index 4a70fd3..90fde77 100644
--- a/itaps/iBase_f.h.in
+++ b/itaps/iBase_f.h.in
@@ -50,7 +50,27 @@
       parameter (iBase_REGION = 3)
       parameter (iBase_ALL_TYPES = 4)
 
-
+      integer iBase_AdjacencyCost_MIN
+      integer iBase_UNAVAILABLE
+      integer iBase_ALL_ORDER_1
+      integer iBase_ALL_ORDER_LOGN
+      integer iBase_ALL_ORDER_N
+      integer iBase_SOME_ORDER_1
+      integer iBase_SOME_ORDER_LOGN
+      integer iBase_SOME_ORDER_N
+      integer iBase_AVAILABLE
+      integer iBase_AdjacencyCost_MAX
+
+      parameter (iBase_AdjacencyCost_MIN = 0)
+      parameter (iBase_UNAVAILABLE = 0)
+      parameter (iBase_ALL_ORDER_1 = 1)
+      parameter (iBase_ALL_ORDER_LOGN = 2)
+      parameter (iBase_ALL_ORDER_N = 3)
+      parameter (iBase_SOME_ORDER_1 = 4)
+      parameter (iBase_SOME_ORDER_LOGN = 5)
+      parameter (iBase_SOME_ORDER_N = 6)
+      parameter (iBase_AVAILABLE = 7)
+      parameter (iBase_AdjacencyCost_MAX = 7)
 
       integer iBase_NEW
       integer iBase_ALREADY_EXISTED

diff --git a/itaps/imesh/Makefile.am b/itaps/imesh/Makefile.am
index 647b8c1..97c76bb 100644
--- a/itaps/imesh/Makefile.am
+++ b/itaps/imesh/Makefile.am
@@ -45,6 +45,9 @@ if PARALLEL
 #  ftest_DEPENDENCIES = libiMesh.la $(top_builddir)/libMOAB.la 
 endif
 
+FCLINK = $(CXXLINK)
+F77LINK = $(CXXLINK)
+
 TESTS = $(check_PROGRAMS)
 LDADD = libiMesh.la $(top_builddir)/src/libMOAB.la ${MOAB_CXX_LINKFLAGS} ${MOAB_CXX_LIBS}
 TESTDEPS = libiMesh.la $(top_builddir)/src/libMOAB.la

diff --git a/moab.make.in b/moab.make.in
index 1e294b3..e6dc42d 100644
--- a/moab.make.in
+++ b/moab.make.in
@@ -10,12 +10,16 @@ MOAB_INCLUDES = -I at abs_srcdir@/src \
 
 MOAB_CXXFLAGS = @CXXFLAGS@ @AM_CXXFLAGS@
 MOAB_CFLAGS = @CFLAGS@ @AM_CFLAGS@
+MOAB_FFLAGS = @FFLAGS@
+MOAB_FCFLAGS = @FCFLAGS@
 MOAB_LDFLAGS = @EXPORT_LDFLAGS@
 
 MOAB_LIBS_LINK = ${MOAB_LDFLAGS} -L${MOAB_LIBDIR} -lMOAB @LIBS@ @PNETCDF_LIBS@ @NETCDF_LIBS@ @HDF5_LIBS@ @CCMIO_LIBS@ @CGM_LIBS@
 
 MOAB_CXX = @CXX@
 MOAB_CC  = @CC@
+MOAB_FC  = @FC@
+MOAB_F77  = @F77@
 
 # Override MOAB_LIBDIR and MOAB_INCLUDES from above with the correct
 # values for the installed MOAB.

diff --git a/src/parallel/WriteHDF5Parallel.cpp b/src/parallel/WriteHDF5Parallel.cpp
index da16c7b..4fbca9e 100644
--- a/src/parallel/WriteHDF5Parallel.cpp
+++ b/src/parallel/WriteHDF5Parallel.cpp
@@ -1680,23 +1680,17 @@ static void convert_to_ranged_ids( const TYPE* buffer,
   }
 
   result.resize( len*2 );
-  std::copy( buffer, buffer+len, result.begin()+len );
-  std::sort( result.begin()+len, result.end() );
-  std::vector<WriteHDF5::id_t>::iterator w = result.begin();
-  std::vector<WriteHDF5::id_t>::const_iterator r = result.begin()+len;
-  *w = *r; ++w;
-  *w = *r; ++r;
-  for (; r != result.end(); ++r) {
-    if (*r == *w + 1) {
-      ++*w;
-    }
-    else {
-      ++w; *w = *r; 
-      ++w; *w = *r;
-    }
+  Range tmp;
+  for (size_t i=0; i<len; i++)
+    tmp.insert( (EntityHandle)buffer[i]);
+  result.resize(tmp.psize()*2);
+  int j=0;
+  for (Range::const_pair_iterator pit=tmp.const_pair_begin();
+      pit!=tmp.const_pair_end(); pit++, j++)
+  {
+    result[2*j]=pit->first;
+    result[2*j+1]=pit->second-pit->first+1;
   }
-  ++w;
-  result.erase( w, result.end() );
 }
 
 static void merge_ranged_ids( const unsigned long* range_list,
@@ -1710,22 +1704,21 @@ static void merge_ranged_ids( const unsigned long* range_list,
   
   result.insert( result.end(), range_list, range_list+len );
   size_t plen = result.size()/2;
-  if (plen > 1) {
-    std::pair<id_t,id_t> *plist = reinterpret_cast<std::pair<id_t,id_t>*>(&result[0]);
-    std::sort( plist, plist+plen );
-    std::pair<id_t,id_t> *wr = plist, *pend = plist+plen;
-    std::sort( plist, pend );
-    for (std::pair<id_t,id_t> *iter = plist+1; iter != pend; ++iter) {
-      if (wr->second+1 < iter->first) {
-        ++wr;
-        *wr = *iter;
-      }
-      else {
-        wr->second = std::max( wr->second, iter->second );
-      }
-    }
-    ++wr;
-    result.resize( 2*(wr - plist) ); 
+  Range tmp;
+  for (size_t i=0; i<plen; i++)
+  {
+    EntityHandle starth=(EntityHandle)result[2*i];
+    EntityHandle endh=(EntityHandle)result[2*i]+(id_t)result[2*i+1]-1; // id+count-1
+    tmp.insert( starth, endh);
+  }
+  // now convert back to std::vector<WriteHDF5::id_t>, compressed range format
+  result.resize(tmp.psize()*2);
+  int j=0;
+  for (Range::const_pair_iterator pit=tmp.const_pair_begin();
+      pit!=tmp.const_pair_end(); pit++, j++)
+  {
+    result[2*j]=pit->first;
+    result[2*j+1]=pit->second-pit->first+1;
   }
 }
 
@@ -1762,12 +1755,13 @@ ErrorCode WriteHDF5Parallel::unpack_set( EntityHandle set,
   
     // If either the current data or the new data is in ranged format,
     // then change the other to ranged format if it isn't already
+  // in both cases when they differ, the data will end up "compressed range"
   std::vector<id_t> tmp;
   if ((flags & mhdf_SET_RANGE_BIT) != (data->setFlags & mhdf_SET_RANGE_BIT)) {
     if (flags & mhdf_SET_RANGE_BIT) {
       tmp = data->contentIds;
       convert_to_ranged_ids( &tmp[0], tmp.size(), data->contentIds );
-      data->setFlags &= mhdf_SET_RANGE_BIT;
+      data->setFlags |= mhdf_SET_RANGE_BIT;
     }
     else {
       tmp.clear();
@@ -1789,7 +1783,7 @@ ErrorCode WriteHDF5Parallel::unpack_set( EntityHandle set,
     }
   }
   
-  if (flags & mhdf_SET_RANGE_BIT)
+  if (data->setFlags & mhdf_SET_RANGE_BIT)
     merge_ranged_ids( contents, num_content, data->contentIds );
   else
     merge_vector_ids( contents, num_content, data->contentIds );

diff --git a/test/parallel/Makefile.am b/test/parallel/Makefile.am
index f1ef1d6..d86a8bf 100644
--- a/test/parallel/Makefile.am
+++ b/test/parallel/Makefile.am
@@ -67,7 +67,7 @@ else
 endif
 
 if ENABLE_mbcslam
-  MBCSLAM_TESTS = par_intx_sph
+  MBCSLAM_TESTS = par_intx_sph 
 else
   MBCSLAM_TESTS = 
 endif
@@ -99,7 +99,7 @@ endif
 
 if ENABLE_mbcslam
   par_intx_sph_SOURCES = par_intx_sph.cpp
-  par_intx_sph_LDADD = $(LDADD) ../../tools/mbcoupler/libmbcoupler.la ../../tools/mbcslam/libmbcslam.la
+  par_intx_sph_LDADD = $(LDADD) ../../tools/mbcoupler/libmbcoupler.la ../../tools/mbcslam/libmbcslam.la  
 endif
 # Other files to clean up (e.g. output from tests)
 MOSTLYCLEANFILES = mhdf_ll.h5m tmp0.h5m tmp1.h5m tmp2.h5m tmp3.h5m

diff --git a/tools/mbcoupler/ElemUtil.cpp b/tools/mbcoupler/ElemUtil.cpp
index 82e7200..96d4d66 100644
--- a/tools/mbcoupler/ElemUtil.cpp
+++ b/tools/mbcoupler/ElemUtil.cpp
@@ -1245,10 +1245,10 @@ namespace Element {
     int n2= _n*_n;
     for (int i=0; i<_n; i++)
     {
-      double csi=_z[0][i];
+      double eta=_z[0][i];
       for (int j=0; j<_n; j++)
       {
-        double eta = _z[1][j]; // we could really use the same _z[0] array of lobatto nodes
+        double csi = _z[1][j]; // we could really use the same _z[0] array of lobatto nodes
         CartVect pos(0.0);
         for (int k = 0; k < 4; k++) {
           const double N_k = (1 + csi*corner_xi[k][0])

diff --git a/tools/mbcslam/CslamUtils.cpp b/tools/mbcslam/CslamUtils.cpp
index c5d6adb..61d1bf0 100644
--- a/tools/mbcslam/CslamUtils.cpp
+++ b/tools/mbcslam/CslamUtils.cpp
@@ -477,7 +477,7 @@ CartVect spherical_to_cart (SphereCoords & sc)
   return res;
 }
 
-ErrorCode SpectralVisuMesh(Interface * mb, Range & input, int NP, EntityHandle & outputSet)
+ErrorCode SpectralVisuMesh(Interface * mb, Range & input, int NP, EntityHandle & outputSet, double tolerance)
 {
   ErrorCode rval = MB_SUCCESS;
 
@@ -485,7 +485,9 @@ ErrorCode SpectralVisuMesh(Interface * mb, Range & input, int NP, EntityHandle &
   moab::Element::SpectralQuad specQuad(NP);
   Range fineElem;
 
+  std::vector<int> gids(input.size()*(NP-1)*(NP-1));// total number of "linear" elements
   // get all edges? or not? Form all gl points + quads, then merge, then output
+  int startGid=0;
   for (Range::iterator it=input.begin(); it!=input.end(); it++)
   {
     const moab::EntityHandle * conn4 = NULL;
@@ -493,7 +495,7 @@ ErrorCode SpectralVisuMesh(Interface * mb, Range & input, int NP, EntityHandle &
     rval = mb->get_connectivity(*it, conn4, num_nodes);
     if (moab::MB_SUCCESS != rval)
     {
-      std::cout << "can't get conectivity for quad \n";
+      std::cout << "can't get connectivity for quad \n";
       return rval;
     }
     assert(num_nodes==4);
@@ -533,6 +535,8 @@ ErrorCode SpectralVisuMesh(Interface * mb, Range & input, int NP, EntityHandle &
         if (rval!=moab::MB_SUCCESS)
           return rval;
         fineElem.insert(element_handle);
+        gids[startGid]=startGid+1;
+        startGid++;
       }
     }
 
@@ -541,7 +545,15 @@ ErrorCode SpectralVisuMesh(Interface * mb, Range & input, int NP, EntityHandle &
   mb->add_entities(outputSet, fineElem);
   // merge all nodes
   MergeMesh mgtool(mb);
-  rval = mgtool.merge_entities(fineElem, 0.0001);
+  rval = mgtool.merge_entities(fineElem, tolerance);
+  if (MB_SUCCESS!=rval)
+    return rval;
+  Tag gidTag;
+  rval = mb->tag_get_handle("GLOBAL_ID", 1, MB_TYPE_INTEGER,
+      gidTag, MB_TAG_DENSE|MB_TAG_CREAT);
+  if (MB_SUCCESS!=rval)
+      return rval;
+  rval = mb->tag_set_data(gidTag, fineElem, &gids[0]);
 
   return rval;
 }

diff --git a/tools/mbcslam/CslamUtils.hpp b/tools/mbcslam/CslamUtils.hpp
index 136d166..e244138 100644
--- a/tools/mbcslam/CslamUtils.hpp
+++ b/tools/mbcslam/CslamUtils.hpp
@@ -83,7 +83,7 @@ CartVect spherical_to_cart (SphereCoords &) ;
  *   output: a set with refined elements; with proper input, it should be pretty
  *   similar to a Homme mesh read with ReadNC
  */
-ErrorCode SpectralVisuMesh(Interface * mb, Range & input, int NP, EntityHandle & outputSet);
+ErrorCode SpectralVisuMesh(Interface * mb, Range & input, int NP, EntityHandle & outputSet, double tolerance);
 
 /*
  * given an entity set, get all nodes and project them on a sphere with given radius

diff --git a/tools/mbcslam/Makefile.am b/tools/mbcslam/Makefile.am
index 0e5542d..2d37b4a 100644
--- a/tools/mbcslam/Makefile.am
+++ b/tools/mbcslam/Makefile.am
@@ -14,7 +14,8 @@ AM_CPPFLAGS += -DSRCDIR=$(srcdir) \
                -I$(top_srcdir)/itaps \
                -I$(top_srcdir)/itaps/imesh \
                -I$(top_builddir)/itaps \
-               -I$(top_builddir)/itaps/imesh
+               -I$(top_builddir)/itaps/imesh \
+               -I$(top_srcdir)/test
 
 lib_LTLIBRARIES = libmbcslam.la
 libmbcslam_la_LIBADD = $(top_builddir)/src/libMOAB.la $(top_builddir)/itaps/imesh/libiMesh.la \
@@ -39,10 +40,16 @@ cfgdir = $(libdir)
 
 TESTS = intx_on_sphere_test  intx_in_plane_test  spec_visu_test spherical_area_test \
          case1_test
+noinst_PROGRAMS = process_arm cslam_par_test
+
 check_PROGRAMS = $(TESTS) 
 intx_on_sphere_test_SOURCES = intx_on_sphere_test.cpp
 intx_in_plane_test_SOURCES = intx_in_plane_test.cpp
 spec_visu_test_SOURCES = spec_visu_test.cpp
 spherical_area_test_SOURCES = spherical_area_test.cpp
 case1_test_SOURCES = case1_test.cpp
+process_arm_SOURCES = process_arm.cpp
+
+cslam_par_test_SOURCES = cslam_par_test.cpp
+cslam_par_test_LDADD = $(LDADD) $(top_builddir)/tools/mbcoupler/libmbcoupler.la 
 

diff --git a/tools/mbcslam/cslam_par_test.cpp b/tools/mbcslam/cslam_par_test.cpp
new file mode 100644
index 0000000..9887047
--- /dev/null
+++ b/tools/mbcslam/cslam_par_test.cpp
@@ -0,0 +1,227 @@
+/*
+ * cslam_par_test.cpp
+ *  test to trigger intersection on a sphere in parallel
+ *  it will start from an eulerian mesh (mesh + velocity from Mark Taylor)
+ *   file: VELO00.h5m; mesh + velo at 850 milibar, in an unstrucured mesh refined from
+ *   a cube sphere grid
+ *  the mesh is read in parallel (euler mesh);
+ *
+ *   lagrangian mesh is obtained using
+ *   pos (t-dt) = pos(t) -Velo(t)*dt
+ *   then, project on the sphere with a given radius
+ *
+ *  Created on: Apr 22, 2013
+ */
+
+#include <iostream>
+#include <sstream>
+#include <time.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "moab/Core.hpp"
+#include "moab/Interface.hpp"
+#include "Intx2MeshOnSphere.hpp"
+#include <math.h>
+#include "TestUtil.hpp"
+#include "moab/ParallelComm.hpp"
+#include "moab/ProgOptions.hpp"
+#include "MBParallelConventions.h"
+#include "moab/ReadUtilIface.hpp"
+#include "MBTagConventions.hpp"
+
+#include "CslamUtils.hpp"
+
+// for M_PI
+#include <math.h>
+
+#ifdef MESHDIR
+std::string TestDir( STRINGIFY(MESHDIR) );
+#else
+std::string TestDir(".");
+#endif
+
+using namespace moab;
+// some input data
+double EPS1=0.2; // this is for box error
+std::string input_mesh_file("VELO00_16p.h5m"); // input file, partitioned correctly
+double Radius = 1.0; // change to radius
+double deltaT = 1.e-6;
+void test_intx_in_parallel_elem_based();
+
+int main(int argc, char **argv)
+{
+  MPI_Init(&argc, &argv);
+  EPS1 = 0.000002;
+  int result = 0;
+
+  if (argc>1)
+  {
+    int index=1;
+    while (index<argc)
+    {
+      if (!strcmp( argv[index], "-eps")) // this is for box error
+      {
+        EPS1=atof(argv[++index]);
+      }
+      if (!strcmp( argv[index], "-input"))
+      {
+        input_mesh_file=argv[++index];
+      }
+      if (!strcmp( argv[index], "-radius"))
+      {
+        Radius=atof(argv[++index]);
+      }
+      if (!strcmp( argv[index], "-deltaT"))
+      {
+        deltaT=atof(argv[++index]);
+      }
+      index++;
+    }
+  }
+  std::cout << " run: -input " << input_mesh_file << "  -eps " << EPS1 <<
+      " -radius " << Radius << " -deltaT " << deltaT << "\n";
+
+  result += RUN_TEST(test_intx_in_parallel_elem_based);
+
+  MPI_Finalize();
+  return result;
+}
+// will save the LOC tag on the euler nodes
+ErrorCode  compute_lagrange_mesh_on_sphere(Interface * mb, EntityHandle euler_set)
+{
+  ErrorCode rval = MB_SUCCESS;
+
+  /*
+   * get all quads first, then vertices, then move them on the surface of the sphere
+   *  radius is 1, usually
+   *  pos (t-dt) = pos(t) -Velo(t)*dt; this will be lagrange mesh, on each processor
+   */
+  Range quads;
+  rval = mb->get_entities_by_type(euler_set, MBQUAD, quads);
+  CHECK_ERR(rval);
+
+  Range connecVerts;
+  rval = mb->get_connectivity(quads, connecVerts);
+
+  // the LOC tag, should be provided by the user?
+  Tag tagh = 0;
+  std::string tag_name("DP");
+  rval = mb->tag_get_handle(tag_name.c_str(), 3, MB_TYPE_DOUBLE, tagh, MB_TAG_DENSE | MB_TAG_CREAT);
+  CHECK_ERR(rval);
+  void *data; // pointer to the DP in memory, for each vertex
+  int count;
+
+  rval = mb->tag_iterate(tagh, connecVerts.begin(), connecVerts.end(), count, data);
+  CHECK_ERR(rval);
+  // here we are checking contiguity
+  assert(count == (int) connecVerts.size());
+  double * ptr_DP=(double*)data;
+  // get the coordinates of the old mesh, and move it around using velocity tag
+
+  Tag tagv = 0;
+  std::string velo_tag_name("VELO");
+  rval = mb->tag_get_handle(velo_tag_name.c_str(), 3, MB_TYPE_DOUBLE, tagv, MB_TAG_DENSE);
+  CHECK_ERR(rval);
+
+  /*void *datavelo; // pointer to the VELO in memory, for each vertex
+
+  rval = mb->tag_iterate(tagv, connecVerts.begin(), connecVerts.end(), count, datavelo);
+  CHECK_ERR(rval);*/
+  // here we are checking contiguity
+  assert(count == (int) connecVerts.size());
+// now put the vertices in the right place....
+  //int vix=0; // vertex index in new array
+
+  for (Range::iterator vit=connecVerts.begin();vit!=connecVerts.end(); vit++ )
+  {
+    EntityHandle oldV=*vit;
+    CartVect posi;
+    rval = mb->get_coords(&oldV, 1, &(posi[0]) );
+    CHECK_ERR(rval);
+    CartVect velo;
+    rval = mb->tag_get_data(tagv, &oldV, 1, (void *) &(velo[0]) );
+    CHECK_ERR(rval);
+    // do some mumbo jumbo, as in python script
+    CartVect newPos = posi - deltaT*velo;
+    double len1= newPos.length();
+    newPos = Radius*newPos/len1;
+
+    ptr_DP[0]=newPos[0];
+    ptr_DP[1]=newPos[1];
+    ptr_DP[2]=newPos[2];
+    ptr_DP+=3; // increment to the next node
+  }
+
+  return rval;
+}
+
+void test_intx_in_parallel_elem_based()
+{
+  std::string opts = std::string("PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION")+
+        std::string(";PARALLEL_RESOLVE_SHARED_ENTS");
+  Core moab;
+  Interface & mb = moab;
+  EntityHandle euler_set;
+  ErrorCode rval;
+  rval = mb.create_meshset(MESHSET_SET, euler_set);
+  CHECK_ERR(rval);
+  std::string example(TestDir + "/" +  input_mesh_file);
+
+  rval = mb.load_file(example.c_str(), &euler_set, opts.c_str());
+
+  ParallelComm* pcomm = ParallelComm::get_pcomm(&mb, 0);
+  CHECK_ERR(rval);
+
+  rval = pcomm->check_all_shared_handles();
+  CHECK_ERR(rval);
+
+  // everybody will get a DP tag, including the non owned entities; so exchange tags is not required for LOC (here)
+  rval = compute_lagrange_mesh_on_sphere(&mb, euler_set);
+  CHECK_ERR(rval);
+
+  int rank = pcomm->proc_config().proc_rank();
+
+  std::stringstream ste;
+  ste<<"initial" << rank<<".vtk";
+  mb.write_file(ste.str().c_str(), 0, 0, &euler_set, 1);
+
+  Intx2MeshOnSphere worker(&mb);
+
+  worker.SetRadius(Radius);
+  worker.set_box_error(EPS1);//
+  worker.SetEntityType(MBQUAD);
+
+  worker.SetErrorTolerance(Radius*1.e-8);
+  std::cout << "error tolerance epsilon_1="<< Radius*1.e-8 << "\n";
+  //  worker.locate_departure_points(euler_set);
+
+  // we need to make sure the covering set is bigger than the euler mesh
+  EntityHandle covering_lagr_set;
+  rval = mb.create_meshset(MESHSET_SET, covering_lagr_set);
+  CHECK_ERR(rval);
+
+  rval = worker.create_departure_mesh_2nd_alg(euler_set, covering_lagr_set);
+  CHECK_ERR(rval);
+
+  std::stringstream ss;
+  ss<<"partial" << rank<<".vtk";
+  mb.write_file(ss.str().c_str(), 0, 0, &covering_lagr_set, 1);
+  EntityHandle outputSet;
+  rval = mb.create_meshset(MESHSET_SET, outputSet);
+  CHECK_ERR(rval);
+  rval = worker.intersect_meshes(covering_lagr_set, euler_set, outputSet);
+  CHECK_ERR(rval);
+
+  //std::string opts_write("PARALLEL=WRITE_PART");
+  //rval = mb.write_file("manuf.h5m", 0, opts_write.c_str(), &outputSet, 1);
+  std::string opts_write("");
+  std::stringstream outf;
+  outf<<"intersect" << rank<<".h5m";
+  rval = mb.write_file(outf.str().c_str(), 0, 0, &outputSet, 1);
+  double intx_area = area_on_sphere(&mb, outputSet, Radius);
+  double arrival_area = area_on_sphere(&mb, euler_set, Radius) ;
+  std::cout<< "On rank : " << rank << " arrival area: " << arrival_area<<
+      "  intersection area:" << intx_area << " rel error: " << fabs((intx_area-arrival_area)/arrival_area) << "\n";
+  CHECK_ERR(rval);
+}

diff --git a/tools/mbcslam/intx_in_plane_test.cpp b/tools/mbcslam/intx_in_plane_test.cpp
index 08e97a4..774e583 100644
--- a/tools/mbcslam/intx_in_plane_test.cpp
+++ b/tools/mbcslam/intx_in_plane_test.cpp
@@ -73,6 +73,19 @@ int main(int argc, char* argv[])
   rval = mb->write_mesh(newFile, &outputSet, 1);
   if (MB_SUCCESS != rval)
     return 1;
+
+  // retrieve polygons and get adjacent edges
+  Range polygons;
+  rval = mb->get_entities_by_type(outputSet, MBPOLYGON, polygons);
+  if (MB_SUCCESS != rval)
+    return 1;
+
+  Range edges;
+  rval = mb->get_adjacencies(polygons, 1, true, edges , Interface::UNION);
+  if (MB_SUCCESS != rval)
+     return 1;
+
+  std::cout << "number of edges:" << edges.size() << "\n";
   return 0;
 
 

diff --git a/tools/mbcslam/process_arm.cpp b/tools/mbcslam/process_arm.cpp
new file mode 100644
index 0000000..ba7642c
--- /dev/null
+++ b/tools/mbcslam/process_arm.cpp
@@ -0,0 +1,404 @@
+/*
+ * process_arm.cpp
+ *
+ *  Created on: April 18, 2013
+ */
+
+// process the files from Mark; also, link against netcdf directly, because we will use
+// netcdf calls to read data, the same as in ReadNC and ReadNCDF
+//
+//
+#include <iostream>
+#include <sstream>
+#include <time.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "moab/Core.hpp"
+#include "moab/Interface.hpp"
+#include "moab/ReadUtilIface.hpp"
+#include "moab/AdaptiveKDTree.hpp"
+
+#include "CslamUtils.hpp"
+
+#include "netcdf.h"
+
+#include <algorithm>
+#include <string>
+#include <assert.h>
+
+#include <cmath>
+
+
+using namespace moab;
+
+#define INS_ID(stringvar, prefix, id) \
+          sprintf(stringvar, prefix, id)
+
+#define GET_DIM(ncdim, name, val)\
+    {                            \
+    int gdfail = nc_inq_dimid(ncFile, name, &ncdim);          \
+    if (NC_NOERR == gdfail) {                                             \
+      size_t tmp_val;                                                   \
+      gdfail = nc_inq_dimlen(ncFile, ncdim, &tmp_val);                        \
+      if (NC_NOERR != gdfail) {                                           \
+        std::cout<<"couldn't get dimension length for" << name<< " \n"; \
+        return 1;                                              \
+      }                                                                 \
+      else val = tmp_val;                                               \
+    } else val = 0;}
+
+#define GET_DIMB(ncdim, name, varname, id, val) \
+          INS_ID(name, varname, id); \
+          GET_DIM(ncdim, name, val);
+
+#define GET_VAR(name, id, dims) \
+    {                           \
+    id = -1;\
+    int gvfail = nc_inq_varid(ncFile, name, &id);   \
+    if (NC_NOERR == gvfail) {       \
+    int ndims;\
+    gvfail = nc_inq_varndims(ncFile, id, &ndims);\
+    if (NC_NOERR == gvfail) {\
+    dims.resize(ndims);    \
+    gvfail = nc_inq_vardimid(ncFile, id, &dims[0]);}}}
+
+#define GET_1D_INT_VAR(name, id, vals) \
+    {GET_VAR(name, id, vals);  \
+  if (-1 != id) {\
+    size_t ntmp;\
+    int ivfail = nc_inq_dimlen(ncFile, vals[0], &ntmp);\
+    vals.resize(ntmp);\
+    size_t ntmp1 = 0;                                                           \
+    ivfail = nc_get_vara_int(ncFile, id, &ntmp1, &ntmp, &vals[0]);\
+    if (NC_NOERR != ivfail) {\
+      std::cout<<"ReadNCDF:: Problem getting variable " <<name <<"\n";\
+      return 1;}}}
+
+
+#define GET_1D_DBL_VAR(name, id, vals) \
+    {std::vector<int> dum_dims;        \
+  GET_VAR(name, id, dum_dims);\
+  if (-1 != id) {\
+    size_t ntmp;\
+    int dvfail = nc_inq_dimlen(ncFile, dum_dims[0], &ntmp);\
+    vals.resize(ntmp);\
+    size_t ntmp1 = 0;                                                           \
+    dvfail = nc_get_vara_double(ncFile, id, &ntmp1, &ntmp, &vals[0]);\
+    if (NC_NOERR != dvfail) {\
+      std::cout<<"ReadNCDF:: Problem getting variable "<< name<<"\n";\
+      return 1;}}}
+
+/*
+int get_2d_flt_var(int ncFile, const char * name, int index, std::vector<float> & vals)
+{
+  int id;
+  std::vector<int> dum_dims;
+  GET_VAR(name, id, dum_dims);
+  if (-1 != id) {
+    size_t ntmp;
+  int dvfail = nc_inq_dimlen(ncFile, dum_dims[1], &ntmp);
+  vals.resize(ntmp);
+  size_t ntmp1[2] = {index, 0};
+
+  int ntimes;
+  dvfail = nc_inq_dimlen(ncFile, dum_dims[0], &ntimes);
+  if (index>=ntimes) {
+    std::cout<<"ReadNCDF:: Problem getting variable "<< name<<"\n";
+    return 1;
+  }
+  size_t count[2] ={1, ntmp};
+  dvfail = nc_get_vara_float(ncFile, id, ntmp1, count, &vals[0]);
+  if (NC_NOERR != dvfail) {
+    std::cout<<"ReadNCDF:: Problem getting variable "<< name<<"\n";
+    return 1;
+  }
+  return 0;
+}
+*/
+/* get the variable along an index */
+#define GET_2D_FLT_VAR(name, id, index, vals) \
+    {std::vector<int> dum_dims;        \
+  GET_VAR(name, id, dum_dims);\
+  if (-1 != id) {\
+    size_t ntmp, ntmp2;\
+    int dvfail = nc_inq_dimlen(ncFile, dum_dims[1], &ntmp);\
+    dvfail = nc_inq_dimlen(ncFile, dum_dims[0], &ntmp2);\
+    vals.resize(ntmp);\
+    size_t ntmp1[2] = {index, 0}; \
+    if (index>=ntmp2) { \
+      std::cout<<"ReadNCDF:: Problem getting variable "<< name<<"\n"; \
+      return 1; \
+    } \
+    size_t count[2] ={1, ntmp}; \
+    dvfail = nc_get_vara_float(ncFile, id, ntmp1, count, &vals[0]);\
+    if (NC_NOERR != dvfail) {\
+      std::cout<<"ReadNCDF:: Problem getting variable "<< name<<"\n";\
+      return 1;}}}
+
+int main(int argc, char ** argv)
+{
+
+  int num_el = 50000;
+  if (argc>1)
+  {
+    num_el = atoi(argv[1]);
+  }
+  std::cout << "num_el=" << num_el << "\n";
+
+  Core moab;
+  Interface & mb = moab;
+  ErrorCode rval;
+
+  int ncFile, temp_dim;        // netcdf/exodus file
+
+  // now, open the data file and read the lat, lon and U850 and V850
+  const char *data_file = "fc5_arm12.cam2.h2.0004-12-12-00000.nc";
+
+  int fail = nc_open(data_file, 0, &ncFile);
+  if (NC_NOWRITE != fail) {
+    std::cout<<"ReadNCDF:: problem opening Netcdf/Exodus II "<<data_file <<"\n";
+    return 1;
+  }
+  int ncol;
+  GET_DIM(temp_dim, "ncol", ncol);
+  std::cout << "ncol:" << ncol << "\n";
+
+  std::vector<double> lat;
+  std::vector<double> lon;
+  GET_1D_DBL_VAR("lat", temp_dim, lat);
+
+  GET_1D_DBL_VAR("lon", temp_dim, lon);
+
+  std::cout<< " lat, lon 0" << lat[0] << " " << lon[0] << "\n";
+  std::cout<< " lat, lon 1" << lat[1] << " " << lon[1] << "\n";
+  std::cout << " size: " << lat.size() << "\n";
+
+  // see if the mesh from metadata makes sense
+  // create quads with the connectivity from conn array
+
+  ReadUtilIface* readMeshIface;
+  mb.query_interface( readMeshIface );
+  if (NULL==readMeshIface)
+    return 1;
+  EntityHandle node_handle = 0;
+  std::vector<double*> arrays;
+  rval = readMeshIface->get_node_coords(3, ncol,
+      1, node_handle, arrays);
+  if (MB_SUCCESS!= rval)
+    return 1;
+
+  SphereCoords  sp;
+  sp.R = 1.;
+  Tag gid;
+  rval = mb.tag_get_handle("GLOBAL_ID", 1, MB_TYPE_INTEGER,
+      gid, MB_TAG_SPARSE|MB_TAG_CREAT);
+  if (MB_SUCCESS!= rval)
+      return 1;
+  std::vector<int> gids(ncol);
+
+  double conversion_factor = M_PI/180.;
+  for (int k=0; k<ncol; k++)
+  {
+    sp.lat=lat[k]*conversion_factor;
+    sp.lon=lon[k]*conversion_factor;
+    CartVect pos=spherical_to_cart (sp);
+    arrays[0][k]=pos[0];
+    arrays[1][k]=pos[1];
+    arrays[2][k]=pos[2];
+    gids[k]=k+1;
+  }
+
+  Range nodes(node_handle, node_handle+ncol-1);
+  rval = mb.tag_set_data(gid, nodes, &gids[0]);
+  if (MB_SUCCESS!= rval)
+       return 1;
+
+  EntityHandle newSet;
+  rval = mb.create_meshset(MESHSET_SET, newSet);
+  if (MB_SUCCESS != rval)
+    return 1;
+
+  // so the nodes will be part
+  mb.add_entities(newSet, nodes);
+
+  // build a kd tree with the vertices
+  EntityHandle tree_root;
+  AdaptiveKDTree kd(&mb, true);
+  rval = kd.build_tree(nodes, tree_root);
+  if (MB_SUCCESS != rval)
+    return 1;
+
+  unsigned int  min_depth, max_depth;
+  rval = kd.depth(tree_root, min_depth, max_depth);
+  if (MB_SUCCESS != rval)
+     return 1;
+  std::cout << "min_depth, max_depth " << min_depth << " " << max_depth << "\n";
+  // now, read the conn file created using spectral visu, and see how they fit
+  // this can be directly imported to moab
+  const char *myconn_file = "spec.R2.vtk";
+  EntityHandle euler_set;
+  rval = mb.create_meshset(MESHSET_SET, euler_set);
+  if (MB_SUCCESS != rval)
+    return 1;
+
+  rval = mb.load_file(myconn_file, &euler_set);
+
+  if (MB_SUCCESS != rval)
+    return 1;
+
+  mb.list_entities(&euler_set, 1);
+
+  Range specQuads;
+  rval = mb.get_entities_by_dimension(euler_set, 2, specQuads );
+  if (MB_SUCCESS != rval)
+     return 1;
+
+  Range vertices;
+  rval = mb.get_connectivity(specQuads, vertices);
+  if (MB_SUCCESS != rval)
+     return 1;
+
+  // do a mapping, from position of vertices to the vertices in the kd tree.
+  // find the closest vertex to each of this
+  std::vector<EntityHandle> mappedTo(vertices.size());
+  std::vector<double> mycoords(vertices.size()*3);
+  rval = mb.get_coords(vertices, &mycoords[0]);
+  double * ptr = &mycoords[0];
+  size_t num_verts=vertices.size();
+  for (size_t i=0; i<num_verts; i++, ptr+=3)
+  {
+    CartVect pos(ptr); // take 3 coordinates
+    std::vector<EntityHandle> leaves;
+    rval = kd.leaves_within_distance( tree_root,
+                                          ptr,
+                                          0.001,
+                                        leaves);
+    if (MB_SUCCESS != rval)
+      return 1;
+    Range closeVerts;
+    for (std::vector<EntityHandle>::iterator vit = leaves.begin(); vit != leaves.end(); vit++)
+    {
+      rval= mb.get_entities_by_handle(*vit, closeVerts, Interface::UNION);
+      if (moab::MB_SUCCESS != rval)
+        return 1;
+    }
+    if (closeVerts.size()<1)
+    {
+      std::cout << "increase tolerance, no points close to " << pos << "\n";
+      return 1;
+    }
+    std::vector<CartVect> coordsTarget(closeVerts.size());
+    rval = mb.get_coords(closeVerts, &(coordsTarget[0][0]));
+    if (MB_SUCCESS != rval)
+      return 1;
+    double minDist2=(pos-coordsTarget[0]).length_squared();
+    EntityHandle closestVertex=closeVerts[0];
+    for (unsigned int j=1; j<closeVerts.size(); j++)
+    {
+      double dist2=(pos-coordsTarget[j]).length_squared();
+      if (minDist2>dist2)
+      {
+        closestVertex = closeVerts[j];
+        minDist2=dist2;
+      }
+    }
+    if (minDist2 > 0.00001)
+    {
+      std::cout << " problem with node " << vertices[i] << "  min dist2:" << minDist2 << "\n";
+      return 1;
+    }
+    mappedTo [i] = closestVertex;
+  }
+
+  num_el = (int)specQuads.size();
+  // tmp_ptr is of type int* and points at the same place as conn
+  EntityHandle * conn = 0;
+
+  EntityHandle elh;
+
+  readMeshIface->get_element_connect(
+          num_el,
+          4,
+          MBQUAD,
+          1,
+          elh,
+          conn);
+
+  EntityHandle firstVertMyMesh=vertices[0];
+  for (int k=0; k<num_el; k++)
+  {
+    const EntityHandle * myconn=0;
+    EntityHandle specElem = specQuads[k];
+    int num_nodes=0;
+    rval = mb.get_connectivity(specElem, myconn, num_nodes);
+    if (MB_SUCCESS != rval || num_nodes !=4)
+      return 1;
+
+    int start_el = k*4;
+    for (int j=0; j<4; j++)
+       conn[start_el+j] = mappedTo[myconn[j]-firstVertMyMesh];
+  }
+  std::cout << " conn:" << conn[0] << " " << conn[1] << " " << conn[3]<< "\n";
+  Range erange(elh, elh+num_el-1);
+
+  mb.add_entities(newSet, erange);
+  std::vector<int> gidels(num_el);
+  Tag gid2;
+  rval = mb.tag_get_handle("GLOBAL_ID_EL", 1, MB_TYPE_INTEGER,
+        gid2, MB_TAG_SPARSE|MB_TAG_CREAT);
+
+  if (MB_SUCCESS != rval)
+      return 1;
+  for (int k=0; k<num_el; k++)
+    gidels[k]=k+1;
+  mb.tag_set_data(gid2, erange, &gidels[0]);
+
+  int times;
+  GET_DIM(temp_dim, "time", times);
+  Tag velotag;
+  rval = mb.tag_get_handle("VELO", 3, MB_TYPE_DOUBLE,
+            velotag, MB_TAG_DENSE|MB_TAG_CREAT);
+  if (MB_SUCCESS!= rval)
+    return 1;
+
+  for (size_t tt=0; tt<56 /*(size_t)times*/; tt++)
+  {
+    // now, read velocities from file:
+    // read the U850 and V850 variables
+    std::vector<float> u850;
+    GET_2D_FLT_VAR("U850", temp_dim, tt, u850);
+    std::vector<float> v850;
+    GET_2D_FLT_VAR("V850", temp_dim, tt, v850);
+
+    std::cout << " U850:" << u850[0] << " " << u850[1] << " " << u850[5] << " "<< u850.size()<<"\n";
+    std::cout << " V850:" << v850[0] << " " << v850[1] << " " << v850[5] << " "<< u850.size()<<"\n";
+    // ok, use radius as 6371km; not needed
+
+    std::vector<CartVect> velo850(ncol);
+
+    std::stringstream fileName;
+    fileName << "VELO0" <<  tt << ".h5m";
+    std::cout << " read velocities at 850 for time:" << tt << "\n";
+
+
+    for (int k=0; k<ncol; k++)
+    {
+      double latRad=lat[k]*conversion_factor;
+      double lonRad=lon[k]*conversion_factor;
+      CartVect U(-sin(lonRad), cos(lonRad), 0.);
+      CartVect V(-sin(latRad)*cos(lonRad), -sin(latRad)*cos(lonRad), cos(latRad));
+      velo850[k]=U*u850[k] +V*v850[k];
+    }
+    rval = mb.tag_set_data(velotag, nodes, &(velo850[0][0]));
+    if (MB_SUCCESS!= rval)
+      return 1;
+    rval = mb.write_mesh(fileName.str().c_str(), &newSet, 1);
+    if (MB_SUCCESS!= rval)
+      return 1;
+  }
+
+
+
+  return 0;
+}

diff --git a/tools/mbcslam/spec_visu_test.cpp b/tools/mbcslam/spec_visu_test.cpp
index 686fde7..54c7e8f 100644
--- a/tools/mbcslam/spec_visu_test.cpp
+++ b/tools/mbcslam/spec_visu_test.cpp
@@ -22,21 +22,25 @@ int main(int argc, char* argv[])
   const char *filename_mesh = STRINGIFY(SRCDIR) "/eulerHomme.vtk";
   const char *newFile = "spectral.vtk";
   int NP = 4; // number of nodes in each direction
-  if (argc == 4)
+  double tolerance = 0.0001;
+  double R = 6.; // should be input
+  if (argc == 6)
   {
     filename_mesh = argv[1];
     NP = atoi(argv[2]);
     newFile = argv[3];
+    R = atof(argv[4]);
+    tolerance = atof(argv[5]);
   }
   else
   {
-    printf("Usage: %s <mesh_filename><NP><newFile>\n", argv[0]);
+    printf("Usage: %s <mesh_filename><NP><newFile><tolerance>\n", argv[0]);
     if (argc != 1)
       return 1;
-    printf("No files specified.  Defaulting to: %s  %d  %s\n",
-        filename_mesh, NP, newFile);
   }
 
+  printf("run:  %s  %d  %s %f %f\n",
+          filename_mesh, NP, newFile, R, tolerance);
   // read input mesh in a set
   ErrorCode rval = MB_SUCCESS;
   Core moab;
@@ -61,11 +65,11 @@ int main(int argc, char* argv[])
   if (MB_SUCCESS != rval)
     return 1;
 
-  rval = SpectralVisuMesh( mb,  inputRange, NP, outputSet);
+  rval = SpectralVisuMesh( mb,  inputRange, NP, outputSet, tolerance);
 
   if (MB_SUCCESS != rval)
     return 1;
-  double R = 6.; // should be input
+
   rval = ProjectOnSphere(mb, outputSet, R);
   if (MB_SUCCESS != rval)
     return 1;


https://bitbucket.org/fathomteam/moab/commits/78a2b51c5349/
Changeset:   78a2b51c5349
Branch:      None
User:        tautges
Date:        2013-05-17 00:24:36
Summary:     Merged fathomteam/moab into master
Affected #:  4 files

diff --git a/src/AEntityFactory.cpp b/src/AEntityFactory.cpp
index 3d04244..577162e 100644
--- a/src/AEntityFactory.cpp
+++ b/src/AEntityFactory.cpp
@@ -788,7 +788,7 @@ ErrorCode AEntityFactory::get_down_adjacency_elements(EntityHandle source_entity
 ErrorCode AEntityFactory::get_down_adjacency_elements_poly(EntityHandle source_entity,
                                                              const unsigned int target_dimension,
                                                              std::vector<EntityHandle> &target_entities,
-                                                             const bool /*create_if_missing*/,
+                                                             const bool create_if_missing,
                                                              const int /*create_adjacency_option*/)
 {
 
@@ -843,6 +843,34 @@ ErrorCode AEntityFactory::get_down_adjacency_elements_poly(EntityHandle source_e
           target_entities.push_back(*adj_edges.begin());
         }
       }
+      else
+      {
+        // we have no adjacent edge yet; we need to create one and also add
+        // them to the adjacency of the vertices
+        if (create_if_missing)
+        {
+          EntityHandle newEdge;
+          EntityHandle v[2] = {vertex_array[i], vertex_array[i+1]};
+          result = thisMB->create_element(MBEDGE, v, 2,
+                                               newEdge);
+          if (MB_SUCCESS!=result)
+            return result;
+          // we also need to add explicit adjacency, so next time we do not
+          // create again (because we do not find the edge if it is not adjacent to the
+          // vertices
+         // if (create_adjacency_option >= 0)
+          //{
+          result = add_adjacency(v[0],newEdge);
+          if (MB_SUCCESS!=result)
+            return result;
+          result = add_adjacency(v[1],newEdge);
+          if (MB_SUCCESS!=result)
+            return result;
+          target_entities.push_back(newEdge);
+          //}
+
+        }
+      }
     }
     return result;
   }
@@ -855,7 +883,7 @@ ErrorCode AEntityFactory::get_down_adjacency_elements_poly(EntityHandle source_e
       std::vector<EntityHandle> dum_vec;
       result = thisMB->get_connectivity(&source_entity, 1, dum_vec);
       if (MB_SUCCESS != result) return result;
-      result = thisMB->get_adjacencies(&dum_vec[0], dum_vec.size(), 1, false,
+      result = thisMB->get_adjacencies(&dum_vec[0], dum_vec.size(), 1, create_if_missing,
                                        target_entities, Interface::UNION);
       return result;
     }

diff --git a/test/MBTest.cpp b/test/MBTest.cpp
index cb6acd9..6d56aca 100644
--- a/test/MBTest.cpp
+++ b/test/MBTest.cpp
@@ -5950,6 +5950,97 @@ ErrorCode mb_poly_adjacency_test()
   return moab.check_adjacencies();
 }
 
+ErrorCode mb_poly_adjacency_test2()
+{
+  ErrorCode rval;
+  Core moab;
+  Interface *mbImpl = &moab;
+
+    // make a polyhedra in shape of a cube with a corner cut
+
+  /*
+   *
+   *             7   -------------   8
+   *          .  |               .   |
+   *       .                  .      |  initial cube had 8 vertices; box [000 - 222]
+   *    5   -------------   6        |   cut a triangle 123 on lower corner
+   *    |        |          |        |
+   *    |                   |        |   faces of the polyhedra (pointing outward)
+   *    |        |          |        |   (123) (24653) (4 10 8 6)
+   *    3                   |        |   (9 10 4 2 1) (7 8 10 9)  (5687)
+   *     \       |          |        |   (1 3 5 7 9)
+   *             9   -  -  -|  -    10
+   *       \  .             |     .
+   *        1,              |  .
+   *  (000)      '2 ----    4
+   *
+   */
+  double coords[] = {0, 1, 0,   // vertex 1
+                     1, 0, 0,   // vertex 2
+                     0, 0 ,1,   // vertex 3
+                     2, 0, 0,
+                     0, 0, 2,
+                     2, 0, 2,   // vertex 6
+                     0, 2, 2,
+                     2, 2, 2,   // vertex 8
+                     0, 2, 0,   // vertex 9
+                     2, 2, 0    // vertex 9
+
+  };
+  EntityHandle verts[10], polygons[7], polyhedron;
+
+  for (int i = 0; i < 10; i++) {
+    rval = mbImpl->create_vertex(&coords[3*i], verts[i]);
+    if (MB_SUCCESS != rval)
+      return rval;
+  }
+
+  EntityHandle connect[]= {1, 2, 3,       // poly 1
+                           2, 4, 6, 5, 3,  // poly 2
+                           4, 10, 8, 6,    // polygon 3...
+                           9, 10, 4, 2, 1,
+                           7, 8, 10, 9,
+                           5, 6, 8, 7,
+                           1, 3, 5, 7, 9   // polygon 7
+                           }; // we know the handles directly
+
+  int num_verts[7]={3, 5, 4, 5, 4, 4, 5};
+  int start_indx[7];
+  start_indx[0]= 0;
+  for (int i=0; i<6; i++)
+    start_indx[i+1]=start_indx[i]+num_verts[i];
+  for (int j = 0; j < 7; j++) {
+    rval = mbImpl->create_element(MBPOLYGON, &connect[start_indx[j]],
+        num_verts[j], polygons[j]);
+    if (MB_SUCCESS != rval)
+      return rval;
+  }
+  rval = mbImpl->create_element(MBPOLYHEDRON, polygons, 7, polyhedron);
+  if (MB_SUCCESS != rval)
+    return rval;
+
+    // create the aentities
+  Range dum_range;
+  for (int dim = 0; dim < 3; dim++) {
+    dum_range.clear();
+    rval = mbImpl->get_adjacencies(&polyhedron, 1, dim, true, dum_range, Interface::UNION);
+    if (MB_SUCCESS != rval)
+      return rval;
+    std::cout << "\n dimension:" << dim << " " << dum_range.size() << " entities";
+  }
+  std::cout << "\n";
+  /*rval=mbImpl->write_mesh("polyhedra.vtk");
+  if (MB_SUCCESS != rval)
+    return rval;*/
+    // delete the polyhedron
+  rval = mbImpl->delete_entities(&polyhedron, 1);
+  if (MB_SUCCESS != rval)
+    return rval;
+
+    // check adjacencies
+  return moab.check_adjacencies();
+}
+
 ErrorCode mb_memory_use_test() 
 {
   Core mb;
@@ -8152,6 +8243,7 @@ int main(int argc, char* argv[])
   RUN_TEST( mb_split_test );
   RUN_TEST( mb_range_seq_intersect_test );
   RUN_TEST( mb_poly_adjacency_test );
+  RUN_TEST( mb_poly_adjacency_test2 );
   RUN_TEST( mb_memory_use_test );
   RUN_TEST( mb_skin_curve_test );
   RUN_TEST( mb_skin_curve_adj_test );

diff --git a/tools/mbcslam/Makefile.am b/tools/mbcslam/Makefile.am
index 2d37b4a..f7785e7 100644
--- a/tools/mbcslam/Makefile.am
+++ b/tools/mbcslam/Makefile.am
@@ -40,7 +40,10 @@ cfgdir = $(libdir)
 
 TESTS = intx_on_sphere_test  intx_in_plane_test  spec_visu_test spherical_area_test \
          case1_test
-noinst_PROGRAMS = process_arm cslam_par_test
+noinst_PROGRAMS =  cslam_par_test
+if NETCDF_FILE
+  noinst_PROGRAMS += process_arm
+endif
 
 check_PROGRAMS = $(TESTS) 
 intx_on_sphere_test_SOURCES = intx_on_sphere_test.cpp

diff --git a/tools/mbcslam/intx_in_plane_test.cpp b/tools/mbcslam/intx_in_plane_test.cpp
index 774e583..d91ea79 100644
--- a/tools/mbcslam/intx_in_plane_test.cpp
+++ b/tools/mbcslam/intx_in_plane_test.cpp
@@ -25,6 +25,7 @@ int main(int argc, char* argv[])
   const char *filename_mesh1 = STRINGIFY(SRCDIR) "/m1.vtk";
   const char *filename_mesh2 = STRINGIFY(SRCDIR) "/m2.vtk";
   const char *newFile = "intx1.vtk";
+  const char *edgesFile = "polyWithEdges.vtk";
   if (argc == 4)
   {
     filename_mesh1 = argv[1];
@@ -86,6 +87,13 @@ int main(int argc, char* argv[])
      return 1;
 
   std::cout << "number of edges:" << edges.size() << "\n";
+  // add edges to the output set
+  rval = mb->add_entities(outputSet, edges);
+  if (MB_SUCCESS != rval)
+    return 1;
+  rval = mb->write_mesh(edgesFile, &outputSet, 1);
+  if (MB_SUCCESS != rval)
+    return 1;
   return 0;
 
 


https://bitbucket.org/fathomteam/moab/commits/bd786b4336d4/
Changeset:   bd786b4336d4
Branch:      None
User:        tautges
Date:        2013-05-23 19:35:23
Summary:     Merged fathomteam/moab into master
Affected #:  8 files

diff --git a/config/compiler.m4 b/config/compiler.m4
index 18df411..81596a6 100644
--- a/config/compiler.m4
+++ b/config/compiler.m4
@@ -126,8 +126,6 @@ fi
 if test "xno" != "x$CHECK_FC"; then
   AC_PROG_FC
   AC_PROG_F77
-  AC_F77_LIBRARY_LDFLAGS
-  AC_FC_LIBRARY_LDFLAGS
 fi
 
 ]) # FATHOM_CHECK_COMPILERS
@@ -523,6 +521,12 @@ case "$cc_compiler:$host_cpu" in
     case "$target_vendor" in
       bgp)
         FATHOM_CC_32BIT=-q32
+	FATHOM_CC_64BIT=-q64
+	AR="ar"
+	NM="nm -B"
+        ;;
+      bgq)
+        FATHOM_CC_32BIT=-q32
         FATHOM_CC_64BIT=-q64
         AR="ar"
         NM="nm -B"

diff --git a/configure.ac b/configure.ac
index 5669a14..2e9646f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -67,14 +67,6 @@ if test "xyes" = "x$ENABLE_FORTRAN" && test "x" != "x$FC"; then
   AC_FC_WRAPPERS
 fi
 
-if test "xyes" = "x$ENABLE_FORTRAN" && test "x" != "x$FLIBS"; then
-   LIBS="$LIBS $FLIBS"
-fi
-
-if test "xyes" = "x$ENABLE_FORTRAN" && test "x" != "x$FCLIBS"; then
-   LIBS="$LIBS $FCLIBS"
-fi
-
 ################################################################################
 #                           Check for need for extra flags to support cray pointers
 ################################################################################
@@ -1232,10 +1224,10 @@ AC_OUTPUT
 AC_MSG_RESULT([C:   $CC $CFLAGS $CPPFLAGS])
 AC_MSG_RESULT([C++: $CXX $CXXFLAGS $CPPFLAGS])
 if test "x" != "x$FC"; then
-  AC_MSG_RESULT([Fortran: $FC $FCFLAGS])
+  AC_MSG_RESULT([Fortran90: $FC $FCFLAGS])
 fi
 if test "x" != "x$F77"; then
-  AC_MSG_RESULT([Fortran: $F77 $FFLAGS])
+  AC_MSG_RESULT([Fortran77: $F77 $FFLAGS])
 fi
 
 if test "x$HAVE_HDF5" = "xno"; then

diff --git a/doc/MOAB-UG.doc b/doc/MOAB-UG.doc
index 567a315..281d619 100644
Binary files a/doc/MOAB-UG.doc and b/doc/MOAB-UG.doc differ

diff --git a/itaps/imesh/FindAdjacencyF90.F90 b/itaps/imesh/FindAdjacencyF90.F90
index 78578a7..8115ef1 100644
--- a/itaps/imesh/FindAdjacencyF90.F90
+++ b/itaps/imesh/FindAdjacencyF90.F90
@@ -69,7 +69,7 @@ program findadjacency
 
      vert_uses = vert_uses + iverts_size
 
-     if (iverts_size .ne. 0) call free(rpverts)
+     if (iverts_size .ne. 0) call iMesh_freeMemory(%VAL(mesh), rpverts)
   end do
 
   ! now get adjacencies in one big block
@@ -81,9 +81,9 @@ program findadjacency
        offsets_size, ierr)
   CHECK("Failure in getEntArrAdj")
 
-  if (allverts_size .ne. 0) call free(rpallverts);
-  if (offsets_size .ne. 0) call free(ipoffsets);
-  if (ents_size .ne. 0) call free(rpents);
+  if (allverts_size .ne. 0) call iMesh_freeMemory(%VAL(mesh), rpallverts);
+  if (offsets_size .ne. 0) call iMesh_freeMemory(%VAL(mesh), ipoffsets);
+  if (ents_size .ne. 0) call iMesh_freeMemory(%VAL(mesh), rpents);
 
   ! compare results of two calling methods
   if (allverts_size .ne. vert_uses) then
@@ -119,6 +119,9 @@ program findadjacency
 !
   write(*, *) "num coords: ", ents_size, " few coords: ", (coords(i), i=0, ents_size/100)  
 
+  call iMesh_freeMemory(%VAL(mesh), verths);
+  call iMesh_freeMemory(%VAL(mesh), pcoord);
+
   call iMesh_dtor(%VAL(mesh), ierr)
   CHECK("Failed to destroy interface")
 

diff --git a/itaps/imesh/Makefile.am b/itaps/imesh/Makefile.am
index 97c76bb..647b8c1 100644
--- a/itaps/imesh/Makefile.am
+++ b/itaps/imesh/Makefile.am
@@ -45,9 +45,6 @@ if PARALLEL
 #  ftest_DEPENDENCIES = libiMesh.la $(top_builddir)/libMOAB.la 
 endif
 
-FCLINK = $(CXXLINK)
-F77LINK = $(CXXLINK)
-
 TESTS = $(check_PROGRAMS)
 LDADD = libiMesh.la $(top_builddir)/src/libMOAB.la ${MOAB_CXX_LINKFLAGS} ${MOAB_CXX_LIBS}
 TESTDEPS = libiMesh.la $(top_builddir)/src/libMOAB.la

diff --git a/itaps/imesh/iMesh_MOAB.cpp b/itaps/imesh/iMesh_MOAB.cpp
index 963e740..6d55492 100644
--- a/itaps/imesh/iMesh_MOAB.cpp
+++ b/itaps/imesh/iMesh_MOAB.cpp
@@ -3423,3 +3423,13 @@ void iMesh_createStructuredMesh(iMesh_Instance instance,
   RETURN(iBase_SUCCESS);
 }
 
+void iMesh_freeMemory(
+        iMesh_Instance instance,
+          /**< [in] iMesh instance handle */
+         void ** ptrToMem)
+{
+  free(*ptrToMem);
+  *ptrToMem=0;
+  return;
+}
+

diff --git a/itaps/imesh/iMesh_extensions.h b/itaps/imesh/iMesh_extensions.h
index 8be6d22..c85571c 100644
--- a/itaps/imesh/iMesh_extensions.h
+++ b/itaps/imesh/iMesh_extensions.h
@@ -399,6 +399,15 @@ void iMesh_createStructuredMesh(
         int *err
           /**< [out] Error flag. */
 );
+/***************************************************************************//**
+ * \brief  Free memory allocated with malloc
+ *
+ ******************************************************************************/
+
+void iMesh_freeMemory(
+        iMesh_Instance instance,
+          /**< [in] iMesh instance handle */
+         void ** ptrToMem);
 
 /***************************************************************************//**
  * \defgroup ScdMesh Structured Mesh

This diff is so big that we needed to truncate the remainder.

https://bitbucket.org/fathomteam/moab/commits/2d50e4c912f9/
Changeset:   2d50e4c912f9
Branch:      None
User:        tautges
Date:        2013-05-23 22:48:48
Summary:     Phase 2 of coupling work: Add BVHTree

- Added BoundBox class, we've needed one forever, and a unit test for it
- Added a BVHTree class, and a test for it

Minor changes:
- fixed a bug in ElemEvaluator where tagSpace wasn't being allocated
- corrected comment in ScdInterface.hpp

Affected #:  27 files

diff --git a/.gitignore b/.gitignore
index 8569087..6d53b03 100644
--- a/.gitignore
+++ b/.gitignore
@@ -169,6 +169,7 @@ test/parallel/*.h5m
 test/parallel/mbparallelcomm_test
 test/parallel/mhdf_parallel
 test/parallel/parallel_hdf5_test
+test/parallel/parallel_unit_tests
 test/parallel/parallel_write_test
 test/parallel/par_coupler_test
 test/parallel/par_intx_sph
@@ -190,10 +191,14 @@ test/perf/point_in_elem
 test/perf/runtest
 test/perf/seqperf
 test/perf/tstt_perf_binding
+test/perf/point_location/elem_eval_time
+test/perf/point_location/point_location
 test/range_test
 test/reorder_test
 test/scdseq_test
 test/seq_man_test
+test/spatial_locator_test
+test/test_boundbox
 test/tag_test
 test/test_adj
 test/test_prog_opt
@@ -210,6 +215,7 @@ tools/dagmc/update_coords
 tools/hexmodops
 tools/mbconvert
 tools/mbcoupler/*.h5m
+tools/mbcoupler/*.g
 tools/mbcoupler/tests/
 tools/mbcslam/case1_test
 tools/mbcslam/intersect1.h5m
@@ -232,3 +238,12 @@ tools/mbzoltan/Config.moab
 tools/spheredecomp
 tools/vtkMOABReader/CMakeLists.txt
 tools/vtkMOABReaderNew/CMakeLists.txt
+tools/vtkMOABReaderNew/CMakeCache.txt
+tools/vtkMOABReaderNew/CMakeFiles/*
+tools/vtkMOABReaderNew/cmake_install.cmake
+tools/vtkMOABReaderNew/vtkMoabReaderPlugin.qrc
+tools/vtkMOABReaderNew/vtkMoabReaderPluginInit.cxx
+tools/vtkMOABReaderNew/vtkMoabReaderPlugin_Plugin.cxx
+tools/vtkMOABReaderNew/vtkMoabReaderPlugin_Plugin.h
+tools/vtkMOABReaderNew/vtkSMvtkMoabReaderPluginInstantiator.cxx
+tools/vtkMOABReaderNew/vtkSMvtkMoabReaderPluginInstantiator.h

diff --git a/src/AdaptiveKDTree.cpp b/src/AdaptiveKDTree.cpp
index 64dd994..6a46e54 100644
--- a/src/AdaptiveKDTree.cpp
+++ b/src/AdaptiveKDTree.cpp
@@ -29,7 +29,7 @@ namespace moab {
 #define MB_AD_KD_TREE_USE_TWO_DOUBLE_TAG
 
     AdaptiveKDTree::AdaptiveKDTree(Interface *iface) 
-    : Tree(iface), planeTag(0), axisTag(0), candidateSplitsPerDir(3), candidatePlaneSet(SUBDIVISION_SNAP)
+    : Tree(iface), planeTag(0), axisTag(0), splitsPerDir(3), planeSet(SUBDIVISION_SNAP)
     {
       boxTagName = treeName;
 
@@ -40,7 +40,7 @@ namespace moab {
 
     AdaptiveKDTree::AdaptiveKDTree(Interface* iface, const Range &entities, 
                                    EntityHandle *tree_root_set, FileOptions *opts) 
-            : Tree(iface), planeTag(0), axisTag(0), candidateSplitsPerDir(3), candidatePlaneSet(SUBDIVISION_SNAP)
+            : Tree(iface), planeTag(0), axisTag(0), splitsPerDir(3), planeSet(SUBDIVISION_SNAP)
     {
       boxTagName = treeName;
       
@@ -82,15 +82,15 @@ namespace moab {
       }
       
         // calculate bounding box of elements
-      CartVect bmin, bmax;
-      rval = compute_bounding_box( *moab(), entities, bmin, bmax);
+      BoundBox box;
+      rval = box.update(*moab(), entities);
       if (MB_SUCCESS != rval)
         return rval;
   
         // create tree root
       EntityHandle tmp_root;
       if (!tree_root_set) tree_root_set = &tmp_root;
-      rval = create_root( bmin.array(), bmax.array(), *tree_root_set);
+      rval = create_root( box.bMin.array(), box.bMax.array(), *tree_root_set);
       if (MB_SUCCESS != rval)
         return rval;
       rval = moab()->add_entities( *tree_root_set, entities );
@@ -98,7 +98,7 @@ namespace moab {
         return rval;
   
       AdaptiveKDTreeIter iter;
-      iter.initialize( this, *tree_root_set, bmin.array(), bmax.array(), AdaptiveKDTreeIter::LEFT );
+      iter.initialize( this, *tree_root_set, box.bMin.array(), box.bMax.array(), AdaptiveKDTreeIter::LEFT );
   
       std::vector<double> tmp_data;
       std::vector<EntityHandle> tmp_data2;
@@ -113,9 +113,9 @@ namespace moab {
         Range best_left, best_right, best_both;
         Plane best_plane = { HUGE_VAL, -1 };
         if ((int)p_count > maxPerLeaf && (int)iter.depth() < maxDepth) {
-          switch (candidatePlaneSet) {
+          switch (planeSet) {
             case AdaptiveKDTree::SUBDIVISION:
-                rval = best_subdivision_plane( candidateSplitsPerDir, 
+                rval = best_subdivision_plane( splitsPerDir, 
                                                iter, 
                                                best_left, 
                                                best_right, 
@@ -124,7 +124,7 @@ namespace moab {
                                                minWidth );
                 break;
             case AdaptiveKDTree::SUBDIVISION_SNAP:
-                rval = best_subdivision_snap_plane( candidateSplitsPerDir, 
+                rval = best_subdivision_snap_plane( splitsPerDir, 
                                                     iter, 
                                                     best_left, 
                                                     best_right, 
@@ -134,7 +134,7 @@ namespace moab {
                                                     minWidth );
                 break;
             case AdaptiveKDTree::VERTEX_MEDIAN:
-                rval = best_vertex_median_plane( candidateSplitsPerDir, 
+                rval = best_vertex_median_plane( splitsPerDir, 
                                                  iter, 
                                                  best_left, 
                                                  best_right, 
@@ -144,7 +144,7 @@ namespace moab {
                                                  minWidth );
                 break;
             case AdaptiveKDTree::VERTEX_SAMPLE:
-                rval = best_vertex_sample_plane( candidateSplitsPerDir, 
+                rval = best_vertex_sample_plane( splitsPerDir, 
                                                  iter, 
                                                  best_left, 
                                                  best_right, 
@@ -178,7 +178,7 @@ namespace moab {
         }
       }
   
-      reset_tree( *tree_root_set );
+      reset_tree();
 
       treeStats.reset();
       
@@ -193,13 +193,13 @@ namespace moab {
         //  SPLITS_PER_DIR: number of candidate splits considered per direction; default = 3
       int tmp_int;
       rval = opts.get_int_option("SPLITS_PER_DIR", tmp_int);
-      if (MB_SUCCESS == rval) candidateSplitsPerDir = tmp_int;
+      if (MB_SUCCESS == rval) splitsPerDir = tmp_int;
 
-        //  CANDIDATE_PLANE_SET: method used to decide split planes; see CandidatePlaneSet enum (below)
+        //  PLANE_SET: method used to decide split planes; see CandidatePlaneSet enum (below)
         //           for possible values; default = 1 (SUBDIVISION_SNAP)
-      rval = opts.get_int_option("CANDIDATE_PLANE_SET", tmp_int);
+      rval = opts.get_int_option("PLANE_SET", tmp_int);
       if (tmp_int < SUBDIVISION || tmp_int > VERTEX_SAMPLE) return MB_FAILURE;
-      else candidatePlaneSet = (CandidatePlaneSet)(tmp_int);
+      else planeSet = (CandidatePlaneSet)(tmp_int);
 
       return MB_SUCCESS;
     }
@@ -318,63 +318,6 @@ namespace moab {
 #endif
     }
 
-
-    ErrorCode AdaptiveKDTree::create_root( const double box_min[3],
-                                           const double box_max[3],
-                                           EntityHandle& root_handle )
-    {
-      ErrorCode rval = moab()->create_meshset( meshsetFlags, root_handle );
-      if (MB_SUCCESS != rval)
-        return rval;
-
-      myRoot = root_handle;
-      
-      double box_tag[6];
-      for (int i = 0; i < 3; i++) {
-        box_tag[i] = box_min[i];
-        box_tag[3+i] = box_max[i];
-      }
-      rval = moab()->tag_set_data(get_box_tag(), &root_handle, 1, box_tag);
-      if (MB_SUCCESS != rval)
-        return rval;
-
-      boxMin = box_min;
-      boxMax = box_max;
-      
-      return MB_SUCCESS;
-    }
-
-    ErrorCode AdaptiveKDTree::reset_tree( EntityHandle root_handle )
-    {
-      ErrorCode rval;
-
-      if (root_handle && myRoot != root_handle) return MB_FAILURE;
-      else if (!root_handle && myRoot) root_handle = myRoot;
-      
-      std::vector<EntityHandle> children, dead_sets, current_sets;
-      current_sets.push_back( root_handle );
-      while (!current_sets.empty()) {
-        EntityHandle set = current_sets.back();
-        current_sets.pop_back();
-        dead_sets.push_back( set );
-        rval = moab()->get_child_meshsets( set, children );
-        if (MB_SUCCESS != rval)
-          return rval;
-        std::copy( children.begin(), children.end(), std::back_inserter(current_sets) );
-        children.clear();
-      }
-  
-      rval = moab()->tag_delete_data( boxTag, &root_handle, 1 );
-      if (MB_SUCCESS != rval)
-        return rval;
-  
-      rval = moab()->delete_entities( &dead_sets[0], dead_sets.size() );
-      if (MB_SUCCESS != rval) return rval;
-
-      myRoot = 0;
-      return MB_SUCCESS;
-    }
-
     ErrorCode AdaptiveKDTree::get_tree_iterator( EntityHandle root,
                                                  AdaptiveKDTreeIter& iter )
     {
@@ -993,17 +936,17 @@ namespace moab {
       }
   
         // sets
-      CartVect tmin, tmax;
+      BoundBox tbox;
       for (i = set_begin; i != elems.end(); ++i) {
         tool->tree_stats().leaf_object_tests()++;
-        rval = tool->compute_bounding_box( *tool->moab(), *i, tmin, tmax);
+        rval = tbox.update(*tool->moab(), *i);
         if (MB_SUCCESS != rval)
           return rval;
     
         bool lo = false, ro = false;
-        if (tmin[plane.norm] <= plane.coord)
+        if (tbox.bMin[plane.norm] <= plane.coord)
           lo = true;
-        if (tmax[plane.norm] >= plane.coord)
+        if (tbox.bMax[plane.norm] >= plane.coord)
           ro = true;
 
         if (lo && ro)
@@ -1392,13 +1335,13 @@ namespace moab {
         // kdtrees never have multiple leaves containing a pt
       if (multiple_leaves) *multiple_leaves = false;
 
-      leaf_it.mBox[0] = boxMin;
-      leaf_it.mBox[1] = boxMax;
+      leaf_it.mBox[0] = boundBox.bMin;
+      leaf_it.mBox[1] = boundBox.bMax;
       
         // test that point is inside tree
-      if (point[0] < boxMin[0] || point[0] > boxMax[0] ||
-          point[1] < boxMin[1] || point[1] > boxMax[1] ||
-          point[2] < boxMin[2] || point[2] > boxMax[2])
+      if (point[0] < boundBox.bMin[0] || point[0] > boundBox.bMax[0] ||
+          point[1] < boundBox.bMin[1] || point[1] > boundBox.bMax[1] ||
+          point[2] < boundBox.bMin[2] || point[2] > boundBox.bMax[2])
         return MB_ENTITY_NOT_FOUND;  
 
         // initialize iterator at tree root
@@ -1460,17 +1403,17 @@ namespace moab {
   
         // Get distance from input position to bounding box of tree
         // (zero if inside box)
-      double min[3], max[3];
-      rval = get_bounding_box(min, max, tree_root);
+      BoundBox box;
+      rval = get_bounding_box(box);
         // if bounding box is not available (e.g. not starting from true root)
         // just start with zero.  Less efficient, but will work.
       node.dist = CartVect(0.0);
       if (MB_SUCCESS == rval) {
         for (int i = 0; i < 3; ++i) {
-          if (from_point[i] < min[i])
-            node.dist[i] = min[i] - from_point[i];
-          else if (from_point[i] > max[i])
-            node.dist[i] = from_point[i] - max[i];
+          if (from_point[i] < box.bMin[i])
+            node.dist[i] = box.bMin[i] - from_point[i];
+          else if (from_point[i] > box.bMax[i])
+            node.dist[i] = from_point[i] - box.bMax[i];
         }
         if (node.dist % node.dist > dist_sqr)
           return MB_SUCCESS;
@@ -1873,11 +1816,12 @@ namespace moab {
         ray_end = HUGE_VAL;
   
         // if root has bounding box, trim ray to that box
-      CartVect bmin, bmax, tvec(tol);
+      CartVect tvec(tol);
+      BoundBox box;
       const CartVect ray_pt( ray_pt_in ), ray_dir( ray_dir_in );
-      rval = get_bounding_box(bmin, bmax, &root);
+      rval = get_bounding_box(box);
       if (MB_SUCCESS == rval) {
-        if (!GeomUtil::segment_box_intersect( bmin-tvec, bmax+tvec, ray_pt, ray_dir, ray_beg, ray_end ))
+        if (!GeomUtil::segment_box_intersect( box.bMin-tvec, box.bMax+tvec, ray_pt, ray_dir, ray_beg, ray_end ))
           return MB_SUCCESS; // ray misses entire tree.
       }
   
@@ -2052,11 +1996,14 @@ namespace moab {
     }
           
     ErrorCode AdaptiveKDTree::get_info(EntityHandle root,
-                                       double min[3], double max[3], 
+                                       double bmin[3], double bmax[3], 
                                        unsigned int &dep) 
     {
-      ErrorCode result = get_bounding_box(min, max, &root);
+      BoundBox box;
+      ErrorCode result = get_bounding_box(box, &root);
       if (MB_SUCCESS != result) return result;
+      box.bMin.get(bmin);
+      box.bMax.get(bmax);
   
       unsigned min_depth;
       return compute_depth( root, min_depth, dep );

diff --git a/src/BVHTree.cpp b/src/BVHTree.cpp
new file mode 100644
index 0000000..f175414
--- /dev/null
+++ b/src/BVHTree.cpp
@@ -0,0 +1,644 @@
+#include "moab/BVHTree.hpp"
+#include "moab/Interface.hpp"
+#include "moab/ElemEvaluator.hpp"
+#include "moab/ReadUtilIface.hpp"
+
+namespace moab 
+{
+    const char *BVHTree::treeName = "BVHTree";
+
+    ErrorCode BVHTree::build_tree(const Range& entities,
+                                  EntityHandle *tree_root_set,
+                                  FileOptions *options) 
+    {
+      ErrorCode rval;
+
+      if (options) {
+        rval = parse_options(*options);
+        if (MB_SUCCESS != rval) return rval;
+
+        if (!options->all_seen()) return MB_FAILURE;
+      }
+      
+        // calculate bounding box of elements
+      BoundBox box;
+      rval = box.update(*moab(), entities);
+      if (MB_SUCCESS != rval)
+        return rval;
+  
+        // create tree root
+      EntityHandle tmp_root;
+      if (!tree_root_set) tree_root_set = &tmp_root;
+      rval = create_root( box.bMin.array(), box.bMax.array(), *tree_root_set);
+      if (MB_SUCCESS != rval)
+        return rval;
+      rval = mbImpl->add_entities( *tree_root_set, entities );
+      if (MB_SUCCESS != rval)
+        return rval;
+  
+        //a fully balanced tree will have 2*_entities.size()
+        //which is one doubling away..
+      std::vector<Node> tree_nodes;
+      tree_nodes.reserve(entities.size()/maxPerLeaf);
+      std::vector<HandleData> handle_data_vec;
+      rval = construct_element_vec(handle_data_vec, entities, boundBox);
+      if (MB_SUCCESS != rval) return rval;
+
+#ifndef NDEBUG
+      for(std::vector<HandleData>::const_iterator i = handle_data_vec.begin(); i != handle_data_vec.end(); ++i) {
+        if(!boundBox.contains_box(i->myBox, 0)){
+          std::cerr << "BB:" << boundBox << "EB:" << i->myBox << std::endl;
+          return MB_FAILURE;
+        }
+      }
+#endif
+        //We only build nonempty trees
+      if(!handle_data_vec.empty()){ 
+          //initially all bits are set
+        tree_nodes.push_back(Node());
+        const int depth = local_build_tree(tree_nodes, handle_data_vec.begin(), handle_data_vec.end(), 0, boundBox);
+#ifndef NDEBUG
+        std::set<EntityHandle> entity_handles;
+        for(std::vector<Node>::iterator n = tree_nodes.begin(); n != tree_nodes.end(); ++n) {
+          for(HandleDataVec::const_iterator j = n->entities.begin(); j != n->entities.end(); ++j) {
+            entity_handles.insert(j->myHandle);
+          }			
+        }
+        if(entity_handles.size() != entities.size()){
+          std::cout << "Entity Handle Size Mismatch!" 
+                    << std::endl;
+        }
+        for(Range::iterator i = entities.begin(); i != entities.end(); ++i) {
+          if (entity_handles.find(*i) == entity_handles.end())
+            std::cout << "Tree is missing an entity! " << std::endl;
+        } 
+#endif
+        treeDepth = std::max(depth, treeDepth);
+      }
+
+        // convert vector of Node's to entity sets and vector of TreeNode's
+      rval = convert_tree(tree_nodes);
+      if (MB_SUCCESS != rval) return rval;
+
+      return rval;
+    }
+
+    ErrorCode BVHTree::convert_tree(std::vector<Node> &tree_nodes) 
+    {
+        // first construct the proper number of entity sets
+      ReadUtilIface *read_util;
+      ErrorCode rval = mbImpl->query_interface(read_util);
+      if (MB_SUCCESS != rval) return rval;
+      
+      rval = read_util->create_entity_sets(tree_nodes.size(), &meshsetFlags, 0, startSetHandle);
+      if (MB_SUCCESS != rval) return rval;
+      rval = mbImpl->release_interface(read_util);
+      if (MB_SUCCESS != rval) return rval;
+
+        // populate the sets and the TreeNode vector
+      EntityHandle set_handle = startSetHandle;
+      std::vector<Node>::iterator it;
+      myTree.reserve(tree_nodes.size());
+      for (it = tree_nodes.begin(); it != tree_nodes.end(); it++, set_handle++) {
+        if (it != tree_nodes.begin() && !it->entities.empty()) {
+          Range range;
+          for (HandleDataVec::iterator hit = it->entities.begin(); hit != it->entities.end(); hit++)
+            range.insert(hit->myHandle);
+          rval = mbImpl->add_entities(set_handle, range);
+          if (MB_SUCCESS != rval) return rval;
+        }
+        myTree.push_back(TreeNode(it->dim, it->child, it->Lmax, it->Rmin, it->box));
+
+        if (it->dim != 3) {
+          rval = mbImpl->add_child_meshset(set_handle, startSetHandle+it->child);
+          if (MB_SUCCESS != rval) return rval;
+          rval = mbImpl->add_child_meshset(set_handle, startSetHandle+it->child+1);
+          if (MB_SUCCESS != rval) return rval;
+        }
+      }
+
+      return MB_SUCCESS;
+    }
+
+    ErrorCode BVHTree::parse_options(FileOptions &opts) 
+    {
+      ErrorCode rval = parse_common_options(opts);
+      if (MB_SUCCESS != rval) return rval;
+      
+        //  SPLITS_PER_DIR: number of candidate splits considered per direction; default = 3
+      int tmp_int;
+      rval = opts.get_int_option("SPLITS_PER_DIR", tmp_int);
+      if (MB_SUCCESS == rval) splitsPerDir = tmp_int;
+
+      return MB_SUCCESS;
+    }
+    
+    void BVHTree::establish_buckets(HandleDataVec::const_iterator begin, 
+                                    HandleDataVec::const_iterator end, 
+                                    const BoundBox &interval, std::vector<std::vector<Bucket> > &buckets) const 
+    {
+        //put each element into its bucket
+      for(HandleDataVec::const_iterator i = begin; i != end; ++i){
+        const BoundBox &box = i->myBox;
+        for (unsigned int dim = 0; dim < 3; ++dim){
+          const unsigned int index = Bucket::bucket_index(splitsPerDir, box, interval, dim);
+          Bucket &bucket = buckets[dim][index];
+          if (bucket.mySize > 0)
+            bucket.boundingBox.update(box);
+          else
+            bucket.boundingBox = box; 
+          bucket.mySize++;
+        }
+      }
+
+#ifndef NDEBUG
+      BoundBox elt_union = begin->myBox;
+      for(HandleDataVec::const_iterator i = begin; i != end; ++i){
+        const BoundBox &box = i->myBox;
+        elt_union.update(box);
+        for (unsigned int dim = 0; dim < 3; ++dim){
+          const unsigned int index = Bucket::bucket_index(splitsPerDir, box, interval, dim);
+          Bucket &bucket = buckets[dim][index];
+          if(!bucket.boundingBox.contains_box(box))
+            std::cerr << "Buckets not covering elements!" << std::endl;
+        }
+      }
+      if(!elt_union.contains_box(interval) ){
+        std::cout << "element union: " << std::endl << elt_union; 
+        std::cout << "intervals: " << std::endl << interval;
+        std::cout << "union of elts does not contain original box!" << std::endl;
+      }
+      if (!interval.contains_box(elt_union) ){
+        std::cout << "original box does not contain union of elts" << std::endl;
+        std::cout << interval << std::endl << elt_union << std::endl;
+      }
+      for(unsigned int d = 0; d < 3; ++d){
+        std::vector<unsigned int> nonempty;
+        const std::vector<Bucket> &buckets_ = buckets[d];
+        unsigned int j = 0;
+        for( std::vector<Bucket>::const_iterator i = buckets_.begin(); 
+             i != buckets_.end(); ++i, ++j){
+          if(i->mySize > 0){ nonempty.push_back(j); }
+        }
+        BoundBox test_box = buckets_[nonempty.front()].boundingBox;
+        for(unsigned int i = 0; i < nonempty.size(); ++i)
+          test_box.update(buckets_[nonempty[i]].boundingBox);
+
+        if(!test_box.contains_box(interval) )
+          std::cout << "union of buckets in dimension: " << d << "does not contain original box!" << std::endl;
+        if (!interval.contains_box(test_box) ) {
+          std::cout << "original box does " << "not contain union of buckets" 
+                    << "in dimension: " << d << std::endl;
+          std::cout << interval << std::endl << test_box << std::endl;
+        }
+      }
+#endif
+    }
+
+    void BVHTree::initialize_splits(std::vector<std::vector<SplitData> > &splits, 
+                                    const std::vector<std::vector<Bucket> > &buckets, 
+                                    const SplitData &data) const {
+      for(unsigned int d = 0; d < 3; ++d){
+        std::vector<SplitData>::iterator splits_begin = splits[d].begin();
+        std::vector<SplitData>::iterator splits_end = splits[d].end();
+        std::vector<Bucket>::const_iterator left_begin = buckets[d].begin();
+        std::vector<Bucket>::const_iterator _end = buckets[d].end();
+        std::vector<Bucket>::const_iterator left_end = buckets[d].begin()+1;
+        for(std::vector<SplitData>::iterator s = splits_begin; s != splits_end; ++s, ++left_end) {
+          s->nl = set_interval(s->leftBox, left_begin, left_end);
+          if(s->nl == 0) { 
+            s->leftBox = data.boundingBox;
+            s->leftBox.bMax[d] = s->leftBox.bMin[d];
+          }
+          s->nr = set_interval(s->rightBox, left_end,  _end);
+          if(s->nr == 0) { 
+            s->rightBox = data.boundingBox;
+            s->rightBox.bMin[d] = s->rightBox.bMax[d];
+          }
+          s->Lmax = s->leftBox.bMax[d];
+          s->Rmin = s->rightBox.bMin[d];
+          s->split = std::distance(splits_begin, s);
+          s->dim = d;
+        }
+#ifndef NDEBUG
+        for(std::vector<SplitData>::iterator s = splits_begin; 
+            s != splits_end; ++s, ++left_end) {
+          BoundBox test_box = s->leftBox;
+          test_box.update(s->rightBox);
+          if(!data.boundingBox.contains_box(test_box)) {
+            std::cout << "nr: " << s->nr << std::endl;
+            std::cout << "Test box: " << std::endl << 
+                test_box;
+            std::cout << "Left box: " << std::endl << 
+                s->leftBox;
+            std::cout << "Right box: " << std::endl << 
+                s->rightBox;
+            std::cout << "Interval: " << std::endl << 
+                data.boundingBox;
+            std::cout << "Split boxes larger than bb" 
+                      << std::endl;
+          }
+          if(!test_box.contains_box(data.boundingBox)) {
+            std::cout << "bb larger than union of split boxes" << std::endl;
+          }         	
+        }
+#endif 
+      }
+    }
+
+    void BVHTree::median_order(HandleDataVec::iterator &begin, 
+                               HandleDataVec::iterator &end, 
+                               SplitData &data) const
+    {
+      int dim = data.dim;
+      for(HandleDataVec::iterator i = begin; i != end; ++i) {
+        i->myDim = 
+            0.5 * (i->myBox.bMin[dim], i->myBox.bMax[dim]);
+      }
+      std::sort(begin, end, BVHTree::HandleData_comparator());
+      const unsigned int total = std::distance(begin, end);
+      HandleDataVec::iterator middle = begin+(total/2);
+      double middle_center = middle->myDim;
+      middle_center += (++middle)->myDim;
+      middle_center *= 0.5;
+      data.split = middle_center;
+      data.nl = std::distance(begin, middle)+1;
+      data.nr = total-data.nl;
+      middle++;
+      data.leftBox  = begin->myBox;
+      data.rightBox = middle->myBox;
+      for(HandleDataVec::iterator i = begin; i != middle; ++i){
+        i->myDim = 0;
+        data.leftBox.update(i->myBox);
+      }
+      for(HandleDataVec::iterator i = middle; i != end; ++i){
+        i->myDim = 1;
+        data.rightBox.update(i->myBox);
+      }
+      data.Rmin = data.rightBox.bMin[data.dim];
+      data.Lmax = data.leftBox.bMax[data.dim];
+#ifndef NDEBUG
+      BoundBox test_box(data.rightBox);
+      if(!data.boundingBox.contains_box(test_box)) {
+        std::cerr << "MEDIAN: BB Does not contain splits" << std::endl;
+      }
+      if(!test_box.contains_box(data.boundingBox)) {
+        std::cerr << "MEDIAN: splits do not contain BB" << std::endl;
+      }
+#endif
+    }
+
+    void BVHTree::find_split(HandleDataVec::iterator &begin, 
+                             HandleDataVec::iterator &end, 
+                             SplitData &data) const
+    {
+      std::vector<std::vector<Bucket> > buckets(3, std::vector<Bucket>(splitsPerDir+1) );
+      std::vector<std::vector<SplitData> > splits(3, std::vector<SplitData>(splitsPerDir, data));
+	
+      const BoundBox interval = data.boundingBox;
+      establish_buckets(begin, end, interval, buckets);
+      initialize_splits(splits, buckets, data);
+      choose_best_split(splits, data);
+      const bool use_median = (0 == data.nl) || (data.nr == 0);
+      if (!use_median)
+        order_elements(begin, end, data);
+      else
+        median_order(begin, end, data);
+
+#ifndef NDEBUG
+      bool seen_one=false,issue=false;
+      bool first_left=true,first_right=true;
+      unsigned int count_left=0, count_right=0;
+      BoundBox left_box, right_box;
+      for(HandleDataVec::iterator i = begin; i != end; ++i){
+        int order = i->myDim;
+        if(order != 0 && order != 1) {
+          std::cerr << "Invalid order element !";
+          std::cerr << order << std::endl;
+          std::exit(-1);
+        }
+        if(order == 1) {
+          seen_one=1;
+          count_right++;
+          if(first_right) {
+            right_box = i->myBox;
+            first_right=false;
+          }
+          else {
+            right_box.update(i->myBox);
+          }
+          if(!right_box.contains_box(i->myBox)) {
+            if(!issue) {
+              std::cerr << "Bounding right box issue!" 
+                        << std::endl;
+            }
+            issue=true;
+          }
+        }
+        if(order==0) {
+          count_left++;
+          if(first_left) {
+            left_box = i->myBox;
+            first_left=false;
+          }
+          else {
+            left_box.update(i->myBox);
+          }
+          if(!data.leftBox.contains_box(i->myBox)) {
+            if(!issue) {
+              std::cerr << "Bounding left box issue!" 
+                        << std::endl;
+            }
+            issue=true;
+          }
+          if(seen_one) {
+            std::cerr << "Invalid ordering!" << std::endl;
+            std::cout << (i-1)->myDim 
+                      << order << std::endl;
+            exit(-1);
+          }
+        }
+      }
+      if(!left_box.contains_box(data.leftBox)) 
+        std::cout << "left elts do not contain left box" << std::endl;
+      if(!data.leftBox.contains_box(left_box)) 
+        std::cout << "left box does not contain left elts" << std::endl;
+      if(!right_box.contains_box(data.rightBox))
+        std::cout << "right elts do not contain right box" << std::endl;
+      if(!data.rightBox.contains_box(right_box))
+        std::cout << "right box do not contain right elts" << std::endl;
+
+      if(count_left != data.nl || count_right != data.nr) {
+        std::cerr << "counts are off!" << std::endl;
+        std::cerr << "total: " 
+                  << std::distance(begin, end) << std::endl;
+        std::cerr << "Dim: " << data.dim << std::endl;
+        std::cerr << data.Lmax << " , " << data.Rmin << std::endl;
+        std::cerr << "Right box: " << std::endl << data.rightBox 
+                  << "Left box: " << std::endl << data.leftBox ;
+        std::cerr << "supposed to be: " << 
+            data.nl << " " << data.nr << std::endl;
+        std::cerr << "accountant says: " << 
+            count_left << " " << count_right << std::endl;
+        std::exit(-1);
+      }
+#endif
+    }
+
+    int BVHTree::local_build_tree(std::vector<Node> &tree_nodes,
+                                  HandleDataVec::iterator begin, 
+                                  HandleDataVec::iterator end,
+                                  const int index, const BoundBox &box, const int depth)
+    {
+#ifndef NDEBUG
+      for(HandleDataVec::const_iterator i = begin; i != end; ++i) {
+        if(!box.contains_box(i->myBox, 0)) {
+          std::cerr << "depth: " << depth << std::endl;
+          std::cerr << "BB:" << box << "EB:" << i->myBox << std::endl;
+          std::exit(-1);
+        }
+      }
+#endif
+
+      const unsigned int total_num_elements = std::distance(begin, end);
+      tree_nodes[index].box = box;
+      
+        //logic for splitting conditions
+      if((int)total_num_elements > maxPerLeaf && depth < maxDepth){
+        SplitData data;
+        data.boundingBox = box;
+        find_split(begin, end, data);
+          //assign data to node
+        tree_nodes[index].Lmax = data.Lmax; tree_nodes[index].Rmin = data.Rmin;
+        tree_nodes[index].dim = data.dim; tree_nodes[index].child = tree_nodes.size();
+          //insert left, right children;
+        tree_nodes.push_back(Node()); tree_nodes.push_back(Node());
+        const int left_depth = local_build_tree(tree_nodes, begin, begin+data.nl, tree_nodes[index].child, 
+                                                data.leftBox, depth+1);
+        const int right_depth = local_build_tree(tree_nodes, begin+data.nl, end, tree_nodes[index].child+1, 
+                                                 data.rightBox, depth+1);
+        return std::max(left_depth, right_depth);
+      }
+
+      tree_nodes[index].dim = 3;
+      std::copy(begin, end, std::back_inserter(tree_nodes[index].entities));
+      return depth;
+    }
+
+    ErrorCode BVHTree::find_point(const std::vector<double> &point, 
+                                  const unsigned int &index,
+                                  const double tol,
+                                  std::pair<EntityHandle, CartVect> &result) const 
+    {
+      const TreeNode &node = myTree[index];
+      CartVect params;
+      bool is_inside;
+      ErrorCode rval = MB_SUCCESS;
+      if(node.dim == 3){
+        Range entities;
+        rval = mbImpl->get_entities_by_handle(startSetHandle+index, entities);
+        if (MB_SUCCESS != rval) return rval;
+        
+        for(Range::iterator i = entities.begin(); i != entities.end(); i++) {
+          myEval->set_ent_handle(*i);
+          myEval->reverse_eval(&point[0], tol, params.array(), &is_inside);
+          if (is_inside) {
+            result.first = *i;
+            result.second = params;
+            return MB_SUCCESS;
+          }
+        }
+        result.first = 0;
+        return MB_SUCCESS;
+      }
+        //the extra tol here considers the case where
+        //0 < Rmin - Lmax < 2tol
+      std::vector<EntityHandle> children;
+      rval = mbImpl->get_child_meshsets(startSetHandle+index, children);
+      if (MB_SUCCESS != rval || children.size() != 2) return rval;
+      
+      if((node.Lmax+tol) < (node.Rmin-tol)){
+        if(point[node.dim] <= (node.Lmax + tol))
+          return find_point(point, children[0]-startSetHandle, tol, result);
+        else if(point[ node.dim] >= (node.Rmin - tol))
+          return find_point(point, children[1]-startSetHandle, tol, result);
+        result = std::make_pair(0, CartVect(&point[0])); //point lies in empty space.
+        return MB_SUCCESS;
+      }
+
+        //Boxes overlap
+        //left of Rmin, you must be on the left
+        //we can't be sure about the boundaries since the boxes overlap
+        //this was a typo in the paper which caused pain.
+      if(point[node.dim] < (node.Rmin - tol))
+        return find_point(point, children[0]-startSetHandle, tol, result);
+        //if you are on the right Lmax, you must be on the right
+      else if(point[ node.dim] > (node.Lmax+tol))
+        return find_point(point, children[1]-startSetHandle, tol, result);
+
+        /* pg5 of paper
+         * However, instead of always traversing either subtree
+         * first (e.g. left always before right), we first traverse 
+         * the subtree whose bounding plane has the larger distance to the 
+         * sought point. This results in less overall traversal, and the correct
+         * cell is identified more quickly.
+         */
+        //Sofar all testing confirms that this 'heuristic' is
+        //significantly slower.
+        //I conjecture this is because it gets improperly
+        //branch predicted..
+        //bool dir = (point[ node.dim] - node.Rmin) <= 
+        //				(node.Lmax - point[ node.dim]);
+      find_point(point, children[0]-startSetHandle, tol, result);
+      if(result.first == 0){ 
+        return find_point(point, children[1]-startSetHandle, tol, result);
+      }
+      return MB_SUCCESS;
+    }
+
+    EntityHandle BVHTree::bruteforce_find(const double *point, const double tol) const {
+      CartVect params;
+      bool is_inside;
+      for(unsigned int i = 0; i < myTree.size(); i++) {
+        if(myTree[i].dim != 3 || !myTree[i].box.contains_point(point, tol)) continue;
+        if (myEval) {
+          Range entities;
+          ErrorCode rval = mbImpl->get_entities_by_handle(startSetHandle+i, entities);
+          if (MB_SUCCESS != rval) return 0;
+          for(Range::iterator j = entities.begin(); j != entities.end(); ++j) {
+            myEval->set_ent_handle(*j);
+            myEval->reverse_eval(point, tol, params.array(), &is_inside);
+            if (is_inside) return *j;
+          }
+        }
+      }
+      return 0;
+    }
+
+    ErrorCode BVHTree::get_bounding_box(BoundBox &box, EntityHandle *tree_node) const 
+    {
+      if (!tree_node || *tree_node == startSetHandle) {
+        box = boundBox;
+        return MB_SUCCESS;
+      }
+      else if ((tree_node && !startSetHandle) ||
+               *tree_node < startSetHandle || *tree_node - startSetHandle > myTree.size()) 
+        return MB_FAILURE;
+
+      box = myTree[tree_node ? *tree_node-startSetHandle : 0].box;
+      return MB_SUCCESS;
+    }
+
+    ErrorCode BVHTree::point_search(const double *point,
+                                    EntityHandle& leaf_out,
+                                    bool *multiple_leaves,
+                                    EntityHandle *start_node) 
+    {
+      std::vector<EntityHandle> children;
+
+      EntityHandle this_set = (start_node ? *start_node : startSetHandle);
+        // convoluted check because the root is different from startSetHandle
+      if (this_set != myRoot &&
+          (this_set < startSetHandle || this_set >= startSetHandle+myTree.size())) 
+        return MB_FAILURE;
+      else if (this_set == myRoot) this_set = startSetHandle;
+      
+      std::vector<EntityHandle> candidates, result_list;     // list of subtrees to traverse, and results 
+      candidates.push_back(this_set-startSetHandle);
+  
+      BoundBox box;
+      while( !candidates.empty() ) {
+        EntityHandle ind = candidates.back();
+        this_set = startSetHandle + ind;
+        candidates.pop_back();
+
+          // test box of this node
+        ErrorCode rval = get_bounding_box(box, &this_set);
+        if (MB_SUCCESS != rval) return rval;
+        if (!box.contains_point(point)) continue;
+
+          // else if not a leaf, test children & put on list
+        else if (myTree[ind].dim != 3) {
+          candidates.push_back(myTree[ind].child);
+          candidates.push_back(myTree[ind].child+1);
+          continue;
+        }
+      
+          // leaf node within distance; return in list
+        result_list.push_back(this_set);
+      }
+
+      if (!result_list.empty()) leaf_out = result_list[0];
+      if (multiple_leaves && result_list.size() > 1) *multiple_leaves = true;
+      return MB_SUCCESS;
+    }
+
+    ErrorCode BVHTree::distance_search(const double from_point[3],
+                                       const double distance,
+                                       std::vector<EntityHandle>& result_list,
+                                       std::vector<double> *result_dists,
+                                       EntityHandle *tree_root)
+    {
+        // non-NULL root should be in tree
+        // convoluted check because the root is different from startSetHandle
+      EntityHandle this_set = (tree_root ? *tree_root : startSetHandle);
+      if (this_set != myRoot &&
+          (this_set < startSetHandle || this_set >= startSetHandle+myTree.size())) 
+        return MB_FAILURE;
+      else if (this_set == myRoot) this_set = startSetHandle;
+
+      const double dist_sqr = distance * distance;
+      const CartVect from(from_point);
+      std::vector<EntityHandle> candidates, result_list_nodes;     // list of subtrees to traverse, and results 
+        // pre-allocate space for default max tree depth
+      candidates.reserve(maxDepth );
+
+        // misc temporary values
+      ErrorCode rval;
+      std::vector<EntityHandle> children;
+      BoundBox box;
+  
+      candidates.push_back(this_set-startSetHandle);
+  
+      while( !candidates.empty() ) {
+
+        EntityHandle ind = candidates.back();
+        this_set = startSetHandle + ind;
+        candidates.pop_back();
+
+          // test box of this node
+        rval = get_bounding_box(box, &this_set);
+        if (MB_SUCCESS != rval) return rval;
+        double d_sqr = box.distance_squared(from_point);
+
+          // if greater than cutoff, continue
+        if (d_sqr > dist_sqr) continue;
+
+          // else if not a leaf, test children & put on list
+        else if (myTree[ind].dim != 3) {
+          candidates.push_back(myTree[ind].child);
+          candidates.push_back(myTree[ind].child+1);
+          continue;
+        }
+      
+          // leaf node within distance; return in list
+        result_list.push_back(this_set);
+        if (result_dists) result_dists->push_back(sqrt(d_sqr));
+      }
+      return MB_SUCCESS;
+    }
+
+    ErrorCode BVHTree::print_nodes(std::vector<Node> &nodes) 
+    {
+      int i;
+      std::vector<Node>::iterator it;
+      for (it = nodes.begin(), i = 0; it != nodes.end(); it++, i++) {
+        std::cout << "Node " << i << ": dim = " << it->dim << ", child = " << it->child << ", Lmax/Rmin = "
+                  << it->Lmax << "/" << it->Rmin << ", box = " << it->box << std::endl;
+      }
+      return MB_SUCCESS;
+    }
+      
+      
+} // namespace moab
+

diff --git a/src/BoundBox.cpp b/src/BoundBox.cpp
new file mode 100644
index 0000000..cb34330
--- /dev/null
+++ b/src/BoundBox.cpp
@@ -0,0 +1,78 @@
+#include "moab/Interface.hpp"
+#include "moab/BoundBox.hpp"
+
+namespace moab 
+{
+    ErrorCode BoundBox::update(Interface &iface, const Range& elems)
+    {
+      ErrorCode rval;
+      bMin = CartVect(HUGE_VAL);
+      bMax = CartVect(-HUGE_VAL);
+      
+      CartVect coords;
+      EntityHandle const *conn, *conn2;
+      int len, len2;
+      Range::const_iterator i;
+  
+        // vertices
+      const Range::const_iterator elem_begin = elems.lower_bound( MBEDGE );
+      for (i = elems.begin(); i != elem_begin; ++i) {
+        rval = iface.get_coords( &*i, 1, coords.array() );
+        if (MB_SUCCESS != rval)
+          return rval;
+        update_min(coords.array());
+        update_max(coords.array());
+      }
+
+        // elements with vertex-handle connectivity list
+      const Range::const_iterator poly_begin = elems.lower_bound( MBPOLYHEDRON, elem_begin );
+      std::vector<EntityHandle> dum_vector;
+      for (i = elem_begin; i != poly_begin; ++i) {
+        rval = iface.get_connectivity( *i, conn, len, true, &dum_vector);
+        if (MB_SUCCESS != rval)
+          return rval;
+
+        for (int j = 0; j < len; ++j) {
+          rval = iface.get_coords( conn+j, 1, coords.array() );
+          if (MB_SUCCESS != rval)
+            return rval;
+          update_min(coords.array());
+          update_max(coords.array());
+        }
+      }
+  
+        // polyhedra
+      const Range::const_iterator set_begin  = elems.lower_bound( MBENTITYSET, poly_begin );
+      for (i = poly_begin; i != set_begin; ++i) {
+        rval = iface.get_connectivity( *i, conn, len, true );
+        if (MB_SUCCESS != rval)
+          return rval;
+
+        for (int j = 0; j < len; ++j) {
+          rval = iface.get_connectivity( conn[j], conn2, len2 );
+          for (int k = 0; k < len2; ++k) {
+            rval = iface.get_coords( conn2+k, 1, coords.array() );
+            if (MB_SUCCESS != rval)
+              return rval;
+            update_min(coords.array());
+            update_max(coords.array());
+          }
+        }
+      }
+  
+        // sets
+      BoundBox box;
+      for (i = set_begin; i != elems.end(); ++i) {
+        Range tmp_elems;
+        rval = iface.get_entities_by_handle(*i, tmp_elems);
+        if (MB_SUCCESS != rval) return rval;
+        rval = box.update(iface, tmp_elems);
+        if (MB_SUCCESS != rval) return rval;
+
+        update(box);
+      }
+  
+      return MB_SUCCESS;
+    }
+
+}

diff --git a/src/LocalDiscretization/ElemEvaluator.cpp b/src/LocalDiscretization/ElemEvaluator.cpp
index 1bf054f..94f544f 100644
--- a/src/LocalDiscretization/ElemEvaluator.cpp
+++ b/src/LocalDiscretization/ElemEvaluator.cpp
@@ -40,7 +40,7 @@ namespace moab {
       int iters=0;
         // while |res| larger than tol
       while (res % res > error_tol_sqr) {
-        if(++iters>25)
+        if(++iters>10)
           return MB_FAILURE;
 
           // get jacobian at current params

diff --git a/src/LocalDiscretization/LinearHex.cpp b/src/LocalDiscretization/LinearHex.cpp
index 20e5229..14de2d9 100644
--- a/src/LocalDiscretization/LinearHex.cpp
+++ b/src/LocalDiscretization/LinearHex.cpp
@@ -96,13 +96,13 @@ namespace moab
 
     ErrorCode LinearHex::reverseEvalFcn(EvalFcn eval, JacobianFcn jacob, InsideFcn ins, 
                                         const double *posn, const double *verts, const int nverts, const int ndim,
-                                        const double tol, double *work, double *params, bool *is_inside) 
+                                        const double tol, double *work, double *params, bool *is_inside)
     {
       assert(posn && verts);
       return EvalSet::evaluate_reverse(eval, jacob, ins, posn, verts, nverts, ndim, tol, work, params, is_inside);
     }
 
-    bool LinearHex::insideFcn(const double *params, const int ndim, const double tol) 
+    bool LinearHex::insideFcn(const double *params, const int ndim, const double tol)
     {
       return EvalSet::inside_function(params, ndim, tol);
     }

diff --git a/src/LocalDiscretization/LinearTet.cpp b/src/LocalDiscretization/LinearTet.cpp
index 2bff33e..705dbee 100644
--- a/src/LocalDiscretization/LinearTet.cpp
+++ b/src/LocalDiscretization/LinearTet.cpp
@@ -38,8 +38,7 @@ namespace moab
       std::vector<double> f0(num_tuples);
       std::copy(field, field+num_tuples, f0.begin());
       std::copy(field, field+num_tuples, result);
-      
-      
+
       for (unsigned i = 1; i < 4; ++i) {
         double p = 0.5*(params[i-1] + 1); // transform from -1 <= p <= 1 to 0 <= p <= 1
         for (int j = 0; j < num_tuples; j++)

diff --git a/src/LocalDiscretization/moab/ElemEvaluator.hpp b/src/LocalDiscretization/moab/ElemEvaluator.hpp
index d7d87a7..b73904a 100644
--- a/src/LocalDiscretization/moab/ElemEvaluator.hpp
+++ b/src/LocalDiscretization/moab/ElemEvaluator.hpp
@@ -300,7 +300,6 @@ namespace moab {
         numTuples = 3;
         tagDim = 0;
         tagHandle = 0;
-        if (numVerts) tagSpace.resize(numVerts*sizeof(double));
         return rval;
       }
       else if (tagHandle != tag) {

diff --git a/src/Makefile.am b/src/Makefile.am
index c50df45..e193dc3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -43,8 +43,10 @@ libMOAB_la_SOURCES = \
   BitPage.hpp \
   BitTag.cpp \
   BitTag.hpp \
+  BoundBox.cpp \
   BSPTree.cpp \
   BSPTreePoly.cpp \
+  BVHTree.cpp \
   CN.cpp \
   CartVect.cpp \
   Core.cpp \
@@ -149,8 +151,10 @@ libMOAB_la_SOURCES = \
 # The list of header files which are to be installed
 nobase_libMOAB_la_include_HEADERS = \
   moab/AdaptiveKDTree.hpp \
+  moab/BoundBox.hpp \
   moab/BSPTree.hpp \
   moab/BSPTreePoly.hpp \
+  moab/BVHTree.hpp \
   moab/CN.hpp \
   moab/CartVect.hpp \
   moab/Compiler.hpp \

diff --git a/src/SpatialLocator.cpp b/src/SpatialLocator.cpp
index 70b0aec..ea9cbf3 100644
--- a/src/SpatialLocator.cpp
+++ b/src/SpatialLocator.cpp
@@ -39,9 +39,9 @@ namespace moab
 
       if (rel_eps && !abs_eps) {
           // relative epsilon given, translate to absolute epsilon using box dimensions
-        CartVect minmax[2];
-        myTree->get_bounding_box(minmax[0], minmax[1]);
-        abs_eps = rel_eps * (minmax[1] - minmax[0]).length();
+        BoundBox box;
+        myTree->get_bounding_box(box);
+        abs_eps = rel_eps * box.diagonal_length();
       }
   
       EntityHandle closest_leaf;

diff --git a/src/Tree.cpp b/src/Tree.cpp
index 54df1a3..d098291 100644
--- a/src/Tree.cpp
+++ b/src/Tree.cpp
@@ -42,95 +42,64 @@ namespace moab
       return MB_SUCCESS;
     }
 
-    static inline void box_accum( const CartVect& point,
-                                  CartVect& bmin,
-                                  CartVect& bmax )
+    ErrorCode Tree::find_all_trees( Range& results )
     {
-      for (unsigned j = 0; j < 3; ++j) {
-        if (point[j] < bmin[j])
-          bmin[j] = point[j];
-        if (point[j] > bmax[j])
-          bmax[j] = point[j];
-      }
+      return moab()->get_entities_by_type_and_tag( 0, MBENTITYSET, &boxTag, 0, 1, results );
     }
 
-    ErrorCode Tree::compute_bounding_box(Interface &iface, const Range& elems, CartVect &box_min, CartVect &box_max)
+    ErrorCode Tree::create_root( const double box_min[3],
+                                 const double box_max[3],
+                                 EntityHandle& root_handle )
     {
-      ErrorCode rval;
-      box_min = CartVect(HUGE_VAL);
-      box_max = CartVect(-HUGE_VAL);
+      ErrorCode rval = mbImpl->create_meshset( meshsetFlags, root_handle );
+      if (MB_SUCCESS != rval)
+        return rval;
+
+      myRoot = root_handle;
       
-      CartVect coords;
-      EntityHandle const *conn, *conn2;
-      int len, len2;
-      Range::const_iterator i;
-  
-        // vertices
-      const Range::const_iterator elem_begin = elems.lower_bound( MBEDGE );
-      for (i = elems.begin(); i != elem_begin; ++i) {
-        rval = iface.get_coords( &*i, 1, coords.array() );
-        if (MB_SUCCESS != rval)
-          return rval;
-        box_accum( coords, box_min, box_max );
+      double box_tag[6];
+      for (int i = 0; i < 3; i++) {
+        box_tag[i] = box_min[i];
+        box_tag[3+i] = box_max[i];
       }
+      rval = mbImpl->tag_set_data(get_box_tag(), &root_handle, 1, box_tag);
+      if (MB_SUCCESS != rval)
+        return rval;
 
-        // elements with vertex-handle connectivity list
-      const Range::const_iterator poly_begin = elems.lower_bound( MBPOLYHEDRON, elem_begin );
-      std::vector<EntityHandle> dum_vector;
-      for (i = elem_begin; i != poly_begin; ++i) {
-        rval = iface.get_connectivity( *i, conn, len, true, &dum_vector);
-        if (MB_SUCCESS != rval)
-          return rval;
+      boundBox.bMin = box_min;
+      boundBox.bMax = box_max;
+      
+      return MB_SUCCESS;
+    }
 
-        for (int j = 0; j < len; ++j) {
-          rval = iface.get_coords( conn+j, 1, coords.array() );
-          if (MB_SUCCESS != rval)
-            return rval;
-          box_accum( coords, box_min, box_max );
-        }
-      }
-  
-        // polyhedra
-      const Range::const_iterator set_begin  = elems.lower_bound( MBENTITYSET, poly_begin );
-      for (i = poly_begin; i != set_begin; ++i) {
-        rval = iface.get_connectivity( *i, conn, len, true );
+    ErrorCode Tree::delete_tree_sets() 
+    {
+      if (!myRoot) return MB_SUCCESS;
+      
+      ErrorCode rval;
+      std::vector<EntityHandle> children, dead_sets, current_sets;
+      current_sets.push_back(myRoot);
+      while (!current_sets.empty()) {
+        EntityHandle set = current_sets.back();
+        current_sets.pop_back();
+        dead_sets.push_back( set );
+        rval = mbImpl->get_child_meshsets( set, children );
         if (MB_SUCCESS != rval)
           return rval;
-
-        for (int j = 0; j < len; ++j) {
-          rval = iface.get_connectivity( conn[j], conn2, len2 );
-          for (int k = 0; k < len2; ++k) {
-            rval = iface.get_coords( conn2+k, 1, coords.array() );
-            if (MB_SUCCESS != rval)
-              return rval;
-            box_accum( coords, box_min, box_max );
-          }
-        }
+        std::copy( children.begin(), children.end(), std::back_inserter(current_sets) );
+        children.clear();
       }
   
-        // sets
-      CartVect tmin, tmax;
-      for (i = set_begin; i != elems.end(); ++i) {
-        Range tmp_elems;
-        rval = iface.get_entities_by_handle(*i, tmp_elems);
-        if (MB_SUCCESS != rval) return rval;
-        rval = compute_bounding_box(iface, tmp_elems, tmin, tmax);
-        if (MB_SUCCESS != rval) return rval;
-      
-        for (int j = 0; j < 3; ++j) {
-          if (tmin[j] < box_min[j])
-            box_min[j] = tmin[j];
-          if (tmax[j] > box_max[j])
-            box_max[j] = tmax[j];
-        }
-      }
+      rval = mbImpl->tag_delete_data( boxTag, &myRoot, 1 );
+      if (MB_SUCCESS != rval)
+        return rval;
   
-      return MB_SUCCESS;
-    }
+      rval = mbImpl->delete_entities( &dead_sets[0], dead_sets.size() );
+      if (MB_SUCCESS != rval) return rval;
 
-    ErrorCode Tree::find_all_trees( Range& results )
-    {
-      return moab()->get_entities_by_type_and_tag( 0, MBENTITYSET, &boxTag, 0, 1, results );
-    }
+      myRoot = 0;
 
+      return MB_SUCCESS;
+    }
+    
 }

diff --git a/src/moab/AdaptiveKDTree.hpp b/src/moab/AdaptiveKDTree.hpp
index a2afea9..d2dfe2f 100644
--- a/src/moab/AdaptiveKDTree.hpp
+++ b/src/moab/AdaptiveKDTree.hpp
@@ -56,7 +56,7 @@ namespace moab {
                                    FileOptions *options = NULL);
 
         //! Reset the tree, optionally checking we have the right root
-      virtual ErrorCode reset_tree(EntityHandle root_handle = 0);
+      virtual ErrorCode reset_tree();
 
         /** \brief Get leaf containing input position.
          *
@@ -229,11 +229,6 @@ namespace moab {
           VERTEX_SAMPLE // = 3
       };
   
-        //! Create tree root node
-      ErrorCode create_root( const double box_min[3],
-                             const double box_max[3],
-                             EntityHandle& root_handle );
-
   private:
 
       friend class AdaptiveKDTreeIter;
@@ -297,9 +292,9 @@ namespace moab {
       
       Tag planeTag, axisTag;
 
-      unsigned candidateSplitsPerDir;
+      unsigned splitsPerDir;
   
-      CandidatePlaneSet candidatePlaneSet;
+      CandidatePlaneSet planeSet;
     };
                     
 
@@ -467,6 +462,11 @@ namespace moab {
                           double& t_enter, double& t_exit ) const;
     };
 
+    inline ErrorCode AdaptiveKDTree::reset_tree()
+    {
+      return delete_tree_sets();
+    }
+
 } // namespace moab 
 
 #endif

diff --git a/src/moab/BVHTree.hpp b/src/moab/BVHTree.hpp
new file mode 100644
index 0000000..b56c456
--- /dev/null
+++ b/src/moab/BVHTree.hpp
@@ -0,0 +1,367 @@
+/**\file BVHTree.hpp
+ * \class moab::BVHTree
+ * \brief Bounding Volume Hierarchy (sorta like a tree), for sorting and searching entities spatially
+ */
+
+#ifndef BVH_TREE_HPP
+#define BVH_TREE_HPP
+
+#include "moab/Interface.hpp"
+#include "moab/CartVect.hpp"
+#include "moab/BoundBox.hpp"
+#include "moab/Tree.hpp"
+#include "moab/Range.hpp"
+#include "moab/CN.hpp"
+
+#include <vector>
+#include <cfloat>
+#include <climits>
+#include <map>
+#include <set>
+#include <iostream>
+
+namespace moab {
+
+    class ElemEvaluator;
+    
+    class BVHTree : public Tree {
+  public:
+      BVHTree(Interface *impl);
+
+      ~BVHTree() {reset_tree();}
+      
+        /** \brief Destroy the tree maintained by this object, optionally checking we have the right root.
+         * \param root If non-NULL, check that this is the root, return failure if not
+         */
+      virtual ErrorCode reset_tree();
+
+      virtual ErrorCode parse_options(FileOptions &opts);
+      
+        /** \brief Get bounding box for tree below tree_node, or entire tree
+         * If no tree has been built yet, returns +/- DBL_MAX for all dimensions.  Note for some tree types,
+         * boxes are not available for non-root nodes, and this function will return failure if non-root
+         * is passed in
+         * \param box The box for this tree
+         * \param tree_node If non-NULL, node for which box is requested, tree root if NULL
+         * \return Only returns error on fatal condition
+         */
+      virtual ErrorCode get_bounding_box(BoundBox &box, EntityHandle *tree_node = NULL) const;
+  
+        /** Build the tree
+         * Build a tree with the entities input.  If a non-NULL tree_root_set pointer is input, 
+         * use the pointed-to set as the root of this tree (*tree_root_set!=0) otherwise construct 
+         * a new root set and pass its handle back in *tree_root_set.  Options vary by tree type;
+         * see Tree.hpp for common options; options specific to AdaptiveKDTree:
+         * SPLITS_PER_DIR: number of candidate splits considered per direction; default = 3
+         * CANDIDATE_PLANE_SET: method used to decide split planes; see CandidatePlaneSet enum (below)
+         *          for possible values; default = 1 (SUBDIVISION_SNAP)
+         * \param entities Entities with which to build the tree
+         * \param tree_root Root set for tree (see function description)
+         * \param opts Options for tree (see function description)
+         * \return Error is returned only on build failure
+         */
+      virtual ErrorCode build_tree(const Range& entities,
+                                   EntityHandle *tree_root_set = NULL,
+                                   FileOptions *options = NULL);
+
+        /** \brief Get leaf containing input position.
+         *
+         * Does not take into account global bounding box of tree.
+         * - Therefore there is always one leaf containing the point.
+         * - If caller wants to account for global bounding box, then
+         * caller can test against that box and not call this method
+         * at all if the point is outside the box, as there is no leaf
+         * containing the point in that case.
+         * \param point Point to be located in tree
+         * \param leaf_out Leaf containing point
+         * \param multiple_leaves Some tree types can have multiple leaves containing a point;
+         *          if non-NULL, this parameter is returned true if multiple leaves contain
+         *          the input point
+         * \param start_node Start from this tree node (non-NULL) instead of tree root (NULL)
+         * \return Non-success returned only in case of failure; not-found indicated by leaf_out=0
+         */
+      virtual ErrorCode point_search(const double *point,
+                                     EntityHandle& leaf_out,
+                                     bool *multiple_leaves = NULL,
+                                     EntityHandle *start_node = NULL);
+
+        /** \brief Find all leaves within a given distance from point
+         * If dists_out input non-NULL, also returns distances from each leaf; if
+         * point i is inside leaf, 0 is given as dists_out[i]
+         * \param from_point Point to be located in tree
+         * \param distance Distance within which to query
+         * \param result_list Leaves within distance or containing point
+         * \param result_dists If non-NULL, will contain distsances to leaves
+         * \param tree_root Start from this tree node (non-NULL) instead of tree root (NULL)
+         */
+      virtual ErrorCode distance_search(const double from_point[3],
+                                        const double distance,
+                                        std::vector<EntityHandle>& result_list,
+                                        std::vector<double> *result_dists,
+                                        EntityHandle *tree_root);
+  private:
+        // don't allow copy constructor, too complicated
+      BVHTree(const BVHTree &s);
+
+      class HandleData 
+      {
+    public:
+        HandleData(EntityHandle h, const BoundBox &bx, const int dp) : myHandle(h), myBox(bx), myDim(dp) {}
+        HandleData() : myHandle(0), myDim(-1) {}
+        EntityHandle myHandle;
+        BoundBox myBox;
+        int myDim;
+      };
+      typedef std::vector<HandleData> HandleDataVec;
+    
+      class SplitData {
+    public:
+        SplitData(): dim(UINT_MAX), nl(UINT_MAX), nr(UINT_MAX), split(DBL_MAX), 
+                     Lmax(-DBL_MAX), Rmin(DBL_MAX) {}
+        SplitData( const SplitData &f): 
+        dim(f.dim), nl(f.nl), nr(f.nr), split(f.split), Lmax(f.Lmax), Rmin(f.Rmin), 
+        boundingBox(f.boundingBox), leftBox(f.leftBox), rightBox(f.rightBox){}
+        unsigned int dim, nl, nr;
+        double split;
+        double Lmax, Rmin;
+        BoundBox boundingBox, leftBox, rightBox;
+        SplitData& operator=(const SplitData & f){
+          dim = f.dim; nl = f.nl; nr = f.nr;
+          split = f.split; Lmax = f.Lmax; Rmin = f.Rmin;
+          boundingBox = f.boundingBox; leftBox = f.leftBox; rightBox = f.rightBox;
+          return *this;
+        }
+      }; //SplitData
+
+      class Split_comparator : 
+          public std::binary_function< SplitData, SplitData, bool> {
+        inline double objective(const SplitData & a) const{
+          return a.Lmax*a.nl - a.Rmin*a.nr;
+        }
+    public:
+        bool operator()(const SplitData &a, const SplitData &b) const {
+          return  objective( a) < objective( b);
+        }
+      }; //Split_comparator
+
+      class HandleData_comparator : 
+          public std::binary_function<HandleData, HandleData, bool> {
+    public:
+        bool operator()(const HandleData &a, const HandleData &b) {
+          return a.myDim < b.myDim ||
+              (a.myDim == b.myDim && 
+               a.myHandle < b.myHandle);
+        }
+      }; //Iterator_comparator
+
+      class Bucket {
+    public:
+        Bucket() : mySize(0) {}
+        Bucket( const Bucket &f): mySize(f.mySize), boundingBox(f.boundingBox) {}
+        Bucket(const unsigned int sz): mySize(sz) {}
+        static unsigned int bucket_index(int num_splits, const BoundBox &box, const BoundBox &interval, const unsigned int dim);
+        unsigned int mySize;
+        BoundBox boundingBox;
+        Bucket &operator=(const Bucket & f){
+          boundingBox = f.boundingBox; mySize = f.mySize;
+          return *this;
+        }
+      }; //Bucket
+
+      class Node {
+    public:
+        HandleDataVec entities;
+        unsigned int dim, child;
+        double Lmax, Rmin;
+        BoundBox box;
+        Node() : dim(-2), child(-1), Lmax(-DBL_MAX), Rmin(DBL_MAX) {}        
+        Node &operator=(const Node& f) {
+          dim = f.dim; child = f.child;
+          Lmax = f.Lmax; Rmin = f.Rmin;
+          entities = f.entities;
+          return *this;
+        }
+      }; // Node
+
+      class TreeNode {
+    public:
+        unsigned int dim, child;
+        double Lmax, Rmin;
+        BoundBox box;
+        TreeNode(int dm, int chld, double lmx, double rmn, BoundBox &bx) 
+                : dim(dm), child(chld), Lmax(lmx), Rmin(rmn), box(bx) {}
+        TreeNode &operator=(const TreeNode& f) {
+          dim = f.dim; child = f.child;
+          Lmax = f.Lmax; Rmin = f.Rmin;
+          return *this;
+        }
+      }; // TreeNode
+
+      void establish_buckets(HandleDataVec::const_iterator begin, 
+                             HandleDataVec::const_iterator end, 
+                             const BoundBox &interval, std::vector<std::vector<Bucket> > &buckets) const;
+
+      unsigned int set_interval(BoundBox & interval, 
+                                std::vector<Bucket>::const_iterator begin, 
+                                std::vector<Bucket>::const_iterator end) const;
+
+      void initialize_splits(std::vector<std::vector<SplitData> > &splits, 
+                             const std::vector<std::vector<Bucket> > &buckets, 
+                             const SplitData &data) const;
+
+      void order_elements(HandleDataVec::iterator &begin, 
+                          HandleDataVec::iterator &end, 
+                          SplitData &data) const;
+
+      void median_order(HandleDataVec::iterator &begin, 
+                        HandleDataVec::iterator &end, 
+                        SplitData & data) const;
+
+      void choose_best_split(const std::vector<std::vector<SplitData> > &splits,
+                             SplitData & data) const;
+
+
+      void find_split(HandleDataVec::iterator &begin, 
+                      HandleDataVec::iterator &end, 
+                      SplitData &data) const;
+
+      ErrorCode find_point(const std::vector<double> &point, 
+                           const unsigned int &index,
+                           const double tol,
+                           std::pair<EntityHandle, CartVect> &result) const;
+      
+      EntityHandle bruteforce_find(const double *point, const double tol) const;
+
+      int local_build_tree(std::vector<Node> &tree_nodes,
+                           HandleDataVec::iterator begin, 
+                           HandleDataVec::iterator end,
+                           const int index, const BoundBox &box, 
+                           const int depth=0);
+
+      ErrorCode construct_element_vec(std::vector<HandleData> &handle_data_vec,
+                                      const Range &elements, 
+                                      BoundBox & bounding_box);
+      
+        // convert the std::vector<Node> to myTree and a bunch of entity sets
+      ErrorCode convert_tree(std::vector<Node> &tree_nodes);
+
+        // print tree nodes
+      ErrorCode print_nodes(std::vector<Node> &nodes);
+      
+      Range entityHandles;
+      std::vector<TreeNode> myTree;
+      ElemEvaluator *myEval;
+      int splitsPerDir;
+      EntityHandle startSetHandle;
+      static const char *treeName;
+    }; //class Bvh_tree
+
+    inline unsigned int BVHTree::Bucket::bucket_index(int num_splits, const BoundBox &box, const BoundBox & interval, const unsigned int dim)
+    {
+//see FastMemoryEfficientCellLocationinUnstructuredGridsForVisualization.pdf 
+//around page 9
+      
+//Paper arithmetic is over-optimized.. this is safer.
+      const double min = interval.bMin[dim];
+      const double length = (interval.bMax[dim]-min)/(num_splits+1);
+      const double center = ((box.bMax[dim] + box.bMin[dim])/2.0)-min;
+#ifndef NDEBUG
+#ifdef BVH_SHOW_INDEX
+      std::cout << "[" << min << " , " 
+                << interval.max[dim] << " ]" <<std::endl;
+      std::cout << "[" 
+                << box.bMin[dim] << " , " << box.bMax[dim] << " ]" <<std::endl;
+      std::cout << "Length of bucket" << length << std::endl;
+      std::cout << "Center: " 
+                << (box.bMax[dim] + box.bMin[dim])/2.0 << std::endl;
+      std::cout << "Distance of center from min:  " << center << std::endl;
+      std::cout << "ratio: " << center/length << std::endl;
+      std::cout << "index: " << std::ceil(center/length)-1 << std::endl;
+#endif
+#endif
+      return std::ceil(center/length)-1;
+    }
+
+    inline BVHTree::BVHTree(Interface *impl) : Tree(impl), splitsPerDir(3) {boxTagName = treeName;}
+
+    inline unsigned int BVHTree::set_interval(BoundBox &interval, 
+                                              std::vector<Bucket>::const_iterator begin, 
+                                              std::vector<Bucket>::const_iterator end) const
+    {
+      bool first=true;
+      unsigned int count = 0;
+      for(std::vector<Bucket>::const_iterator b = begin; b != end; ++b) {
+        const BoundBox &box = b->boundingBox;
+        count += b->mySize;
+        if(b->mySize != 0){
+          if(first){
+            interval = box;
+            first=false;
+          }
+          else
+            interval.update(box);
+        }
+      }
+      return count;
+    }
+
+    inline void BVHTree::order_elements(HandleDataVec::iterator &begin, 
+                                        HandleDataVec::iterator &end, 
+                                        SplitData &data) const  
+    {
+      for(HandleDataVec::iterator i = begin; i != end; ++i) 
+      {
+        const int index = Bucket::bucket_index(splitsPerDir, i->myBox, data.boundingBox, data.dim);
+        i->myDim = (index<=data.split)?0:1;
+      }
+      std::sort(begin, end, HandleData_comparator());
+    }
+
+    inline void BVHTree::choose_best_split(const std::vector<std::vector<SplitData> > &splits,
+                                           SplitData &data) const
+    {
+      std::vector<SplitData> best_splits;
+      for(std::vector<std::vector<SplitData> >::const_iterator i = splits.begin(); i != splits.end(); ++i){
+        std::vector<SplitData>::const_iterator j = std::min_element((*i).begin(), (*i).end(), 
+                                                                    Split_comparator());
+        best_splits.push_back(*j);
+      }
+      data = *std::min_element(best_splits.begin(), best_splits.end(), Split_comparator());
+    }
+
+    inline ErrorCode BVHTree::construct_element_vec(std::vector<HandleData> &handle_data_vec,
+                                                    const Range &elements, 
+                                                    BoundBox & bounding_box) 
+    {
+      std::vector<double> coordinate(3*CN::MAX_NODES_PER_ELEMENT);
+      int num_conn;
+      ErrorCode rval = MB_SUCCESS;
+      std::vector<EntityHandle> storage;
+      for(Range::iterator i = elements.begin(); i != elements.end(); ++i) {
+          //TODO: not generic enough. Why dim != 3
+          //Commence un-necessary deep copying.
+        const EntityHandle* connect;
+        rval = mbImpl->get_connectivity(*i, connect, num_conn, false, &storage);
+        if (MB_SUCCESS != rval) return rval;
+        rval = mbImpl->get_coords(connect, num_conn, &coordinate[0]);
+        if (MB_SUCCESS != rval) return rval;
+        BoundBox box;
+        for(int j = 0; j < num_conn; j++)
+          box.update(&coordinate[3*j]);
+        if(i == elements.begin())
+          bounding_box = box;
+        else bounding_box.update(box);
+        handle_data_vec.push_back(HandleData(*i, box, 0.0));
+      }
+
+      return rval;
+    }
+
+    inline ErrorCode BVHTree::reset_tree()
+    {
+      return delete_tree_sets();
+    }
+
+} // namespace moab
+
+#endif //BVH_TREE_HPP

diff --git a/src/moab/BoundBox.hpp b/src/moab/BoundBox.hpp
new file mode 100644
index 0000000..0cf543a
--- /dev/null
+++ b/src/moab/BoundBox.hpp
@@ -0,0 +1,174 @@
+#ifndef BOUND_BOX_HPP
+#define BOUND_BOX_HPP
+
+#include "moab/Interface.hpp"
+#include "moab/CartVect.hpp"
+
+#include <cfloat>
+
+namespace moab {
+
+    class BoundBox {
+  public:
+      BoundBox() : bMin(DBL_MAX), bMax(-DBL_MAX) {}
+      BoundBox(const CartVect &min, const CartVect &max) : 
+              bMin(min), bMax(max) {}
+      BoundBox(const double *corners);
+      ~BoundBox() {}
+
+      bool contains_point(const double *point, const double tol = 0.0) const;
+      bool contains_box(const BoundBox &b, const double tol = 0.0) const;
+      void compute_center(CartVect &center);
+      void update(const BoundBox &other_box);
+      void update(const double *coords);
+      ErrorCode update(Interface &iface, const Range& elems);
+      ErrorCode update(Interface &iface, const EntityHandle ent);
+      void update_min(const BoundBox &other_box);
+      void update_min(const double *coords);
+      void update_max(const BoundBox &other_box);
+      void update_max(const double *coords);
+
+        /** \brief Return the diagonal length of this box
+         */
+      double diagonal_length() const;
+      
+        /** \brief Return the square of the diagonal length of this box
+         */
+      double diagonal_squared() const;
+      
+        /** \brief Return square of distance from box, or zero if inside 
+         * \param from_point Point from which you want distance_sq
+         */
+      double distance_squared(const double *from_point) const;
+
+        /** \brief Return distance from box, or zero if inside 
+         * \param from_point Point from which you want distance
+         */
+      double distance(const double *from_point) const;
+      
+      BoundBox &operator=(const BoundBox &from) {
+        bMin = from.bMin;
+        bMax = from.bMax;
+        return *this;
+      }
+
+      CartVect bMin, bMax;
+    };
+    
+    inline BoundBox::BoundBox(const double *corners) 
+    {
+        // relies on CartVect being Plain Old Data, no virtual table
+      double *arr = bMin.array();
+      for (int i = 0; i < 6; i++)
+        arr[i] = corners[i];
+    }
+
+    inline bool BoundBox::contains_point(const double *point, const double tol) const {
+      if (point[0] > bMin[0]-tol && point[0] < bMax[0]+tol &&
+          point[1] > bMin[1]-tol && point[1] < bMax[1]+tol &&
+          point[2] > bMin[2]-tol && point[2] < bMax[2]+tol)
+        return true;
+      else return false;
+    }
+
+    inline bool BoundBox::contains_box(const BoundBox &b, const double tol) const {
+      if (b.bMin[0] < bMin[0]-tol || b.bMax[0] > bMax[0]+tol ||
+          b.bMin[1] < bMin[1]-tol || b.bMax[1] > bMax[1]+tol ||
+          b.bMin[2] < bMin[2]-tol || b.bMax[2] > bMax[2]+tol) 
+        return false;
+
+      else return true;
+    }
+
+    inline void BoundBox::update(const BoundBox &other_box) 
+    {
+      update_min(other_box);
+      update_max(other_box);
+    }
+
+    inline void BoundBox::update(const double *coords) 
+    {
+      update_min(coords);
+      update_max(coords+3);
+    }
+
+    inline void BoundBox::update_min(const BoundBox &other_box) 
+    {
+      bMin[0] = std::min(bMin[0], other_box.bMin[0]);
+      bMin[1] = std::min(bMin[1], other_box.bMin[1]);
+      bMin[2] = std::min(bMin[2], other_box.bMin[2]);
+    }
+      
+    inline void BoundBox::update_min(const double *coords) 
+    {
+      bMin[0] = std::min(bMin[0], coords[0]);
+      bMin[1] = std::min(bMin[1], coords[1]);
+      bMin[2] = std::min(bMin[2], coords[2]);
+    }
+      
+    inline void BoundBox::update_max(const BoundBox &other_box)
+    {
+      bMax[0] = std::max(bMax[0], other_box.bMax[0]);
+      bMax[1] = std::max(bMax[1], other_box.bMax[1]);
+      bMax[2] = std::max(bMax[2], other_box.bMax[2]);
+    }
+
+    inline void BoundBox::update_max(const double *coords)
+    {
+      bMax[0] = std::max(bMax[0], coords[0]);
+      bMax[1] = std::max(bMax[1], coords[1]);
+      bMax[2] = std::max(bMax[2], coords[2]);
+    }
+
+    inline void BoundBox::compute_center(CartVect &center){
+      center = 0.5 * (bMin + bMax);
+    }
+
+    inline std::ostream &operator<<(std::ostream& out, const BoundBox &box) {
+      out << "Max: ";
+      out << box.bMax;
+      out << "Min: ";
+      out << box.bMin;
+      return out;
+    }
+
+    inline ErrorCode BoundBox::update(Interface &iface, const EntityHandle ent) 
+    {
+      Range tmp_range(ent, ent);
+      return update(iface, tmp_range);
+    }
+
+    inline double BoundBox::distance_squared(const double *from_point) const
+    {
+      double dist_sq = 0.0;
+      for (int i = 0; i < 3; ++i) {
+        if (from_point[i] < bMin[i])
+          dist_sq += (bMin[i] - from_point[i]) * (bMin[i] - from_point[i]);
+        else if (from_point[i] > bMax[i]) 
+          dist_sq += (bMax[i] - from_point[i]) * (bMax[i] - from_point[i]);
+      }
+      return dist_sq;
+    }
+
+    inline double BoundBox::distance(const double *from_point) const
+    {
+      double dist_sq = distance_squared(from_point);
+      return sqrt(dist_sq);
+    }
+
+    inline double BoundBox::diagonal_length() const 
+    {
+      if (DBL_MAX == bMax[0] || DBL_MAX == bMax[1] || DBL_MAX == bMax[2] ||
+          DBL_MAX == bMin[0] || DBL_MAX == bMin[1] || DBL_MAX == bMin[2]) return DBL_MAX;
+      return (bMax - bMin).length();
+    }
+
+    inline double BoundBox::diagonal_squared() const 
+    {
+      if (DBL_MAX == bMax[0] || DBL_MAX == bMax[1] || DBL_MAX == bMax[2] ||
+          DBL_MAX == bMin[0] || DBL_MAX == bMin[1] || DBL_MAX == bMin[2]) return DBL_MAX;
+      return (bMax - bMin).length_squared();
+    }
+}
+
+#endif

diff --git a/src/moab/ScdInterface.hpp b/src/moab/ScdInterface.hpp
index 3c3e6d1..bb2ae25 100644
--- a/src/moab/ScdInterface.hpp
+++ b/src/moab/ScdInterface.hpp
@@ -157,8 +157,8 @@ public:
      * the mesh, call the destroy_mesh function on the ScdBox object first, before destroying it.
      * \param low Lower corner in parameter space
      * \param high Higher corner in parameter space
-     * \param coords Coordinates of vertices, interleaved (xyzxyz...); if NULL, no coords are set
-     * \param num_coords Number of coordinate values; if zero, no coords are set
+     * \param coords Coordinates of vertices, interleaved (xyzxyz...); if NULL, coords are set to parametric values
+     * \param num_coords Number of coordinate values
      * \param new_box Reference to box of structured mesh
      * \param lperiodic[2] If lperiodic[s] != 0, direction s is locally periodic
      * \param par_data If non-NULL, this will get stored on the ScdBox once created, contains info

diff --git a/src/moab/SpatialLocator.hpp b/src/moab/SpatialLocator.hpp
index 907a133..a8f694f 100644
--- a/src/moab/SpatialLocator.hpp
+++ b/src/moab/SpatialLocator.hpp
@@ -32,7 +32,7 @@ namespace moab {
       ErrorCode add_elems(Range &elems);
       
         /* get bounding box of this locator */
-      ErrorCode get_bounding_box(CartVect &box_min, CartVect &box_max);
+      ErrorCode get_bounding_box(BoundBox &box);
       
         /* locate a set of points */
       ErrorCode locate_points(const double *pos, int num_points,
@@ -83,9 +83,9 @@ namespace moab {
       return locate_points(pos, 1, &ent, params, rel_tol, abs_tol, is_inside);
     }
 
-    inline ErrorCode SpatialLocator::get_bounding_box(CartVect &box_min, CartVect &box_max) 
+    inline ErrorCode SpatialLocator::get_bounding_box(BoundBox &box) 
     {
-      return myTree->get_bounding_box(box_min, box_max);
+      return myTree->get_bounding_box(box);
     }
 
 } // namespace moab 

This diff is so big that we needed to truncate the remainder.

https://bitbucket.org/fathomteam/moab/commits/4a4f6c1f81cb/
Changeset:   4a4f6c1f81cb
Branch:      None
User:        tautges
Date:        2013-05-24 18:33:31
Summary:     - Adding tree stats keeping and printing
- fixed Tree::find_all_trees to use initialized box tag
- added operator== to BoundBox and CartVect
- made TreeStats member variables all public, like BoundBox
- fixed kd_tree_tool test to work with new Tree defaults
- spatial_locator_test now prints tree stats

Affected #:  11 files

diff --git a/src/AdaptiveKDTree.cpp b/src/AdaptiveKDTree.cpp
index 6a46e54..ecb8cb2 100644
--- a/src/AdaptiveKDTree.cpp
+++ b/src/AdaptiveKDTree.cpp
@@ -12,6 +12,7 @@
 #include <algorithm>
 #include <limits>
 #include <iostream>
+#include <cstdio>
 
 namespace moab {
 
@@ -171,8 +172,11 @@ namespace moab {
         }
         else {
           rval = iter.step();
-          if (MB_ENTITY_NOT_FOUND == rval) 
-            return MB_SUCCESS;  // at end
+          if (MB_ENTITY_NOT_FOUND == rval) {
+            treeStats.reset();
+            rval = treeStats.compute_stats(mbImpl, myRoot);
+            return rval;  // at end
+          }
           else if (MB_SUCCESS != rval)
             break;
         }
@@ -198,7 +202,8 @@ namespace moab {
         //  PLANE_SET: method used to decide split planes; see CandidatePlaneSet enum (below)
         //           for possible values; default = 1 (SUBDIVISION_SNAP)
       rval = opts.get_int_option("PLANE_SET", tmp_int);
-      if (tmp_int < SUBDIVISION || tmp_int > VERTEX_SAMPLE) return MB_FAILURE;
+      if (MB_SUCCESS == rval && (tmp_int < SUBDIVISION || tmp_int > VERTEX_SAMPLE)) return MB_FAILURE;
+      else if (MB_ENTITY_NOT_FOUND == rval) planeSet = SUBDIVISION;
       else planeSet = (CandidatePlaneSet)(tmp_int);
 
       return MB_SUCCESS;
@@ -516,12 +521,12 @@ namespace moab {
   
       for (;;) {
         childVect.clear();
-        treeTool->treeStats.nodes_visited()++; // not sure whether this is the visit or the push_back below
+        treeTool->treeStats.nodesVisited++; // not sure whether this is the visit or the push_back below
         rval = treeTool->moab()->get_child_meshsets( mStack.back().entity, childVect );
         if (MB_SUCCESS != rval)
           return rval;
         if (childVect.empty()) { // leaf
-          treeTool->treeStats.leaves_visited()++;
+          treeTool->treeStats.leavesVisited++;
           break;
         }
   
@@ -553,8 +558,8 @@ namespace moab {
         // If the stack is empty after this pop, then we've reached the end.
       node = mStack.back();
       mStack.pop_back();
-      treeTool->treeStats.nodes_visited()++;
-      if (mStack.empty()) treeTool->treeStats.leaves_visited()++;
+      treeTool->treeStats.nodesVisited++;
+      if (mStack.empty()) treeTool->treeStats.leavesVisited++;
 
       while(!mStack.empty()) {
           // Get data for parent entity
@@ -573,7 +578,7 @@ namespace moab {
           mBox[direction][plane.norm] = node.coord;
             // push right child on stack
           node.entity = childVect[direction];
-          treeTool->treeStats.nodes_visited()++; // changed node
+          treeTool->treeStats.nodesVisited++; // changed node
           node.coord = mBox[opposite][plane.norm];
           mStack.push_back( node );
             // change from box of parent to box of right child
@@ -587,7 +592,7 @@ namespace moab {
         assert( childVect[direction] == node.entity );
         mBox[opposite][plane.norm] = node.coord;
         node = parent;
-        treeTool->treeStats.nodes_visited()++;
+        treeTool->treeStats.nodesVisited++;
         mStack.pop_back();
       }
   
@@ -790,7 +795,7 @@ namespace moab {
                                             double& t_enter, 
                                             double& t_exit ) const
     {
-      treeTool->treeStats.leaf_object_tests()++;
+      treeTool->treeStats.leafObjectTests++;
       return GeomUtil::ray_box_intersect( CartVect(box_min()),
                                           CartVect(box_max()),
                                           CartVect(ray_point),
@@ -842,7 +847,7 @@ namespace moab {
   
         // vertices
       for (i = elems.begin(); i != elem_begin; ++i) {
-        tool->tree_stats().leaf_object_tests()++;
+        tool->tree_stats().leafObjectTests++;
         rval = moab->get_coords( &*i, 1, coords[0].array() );
         if (MB_SUCCESS != rval)
           return rval;
@@ -864,7 +869,7 @@ namespace moab {
         // non-polyhedron elements
       std::vector<EntityHandle> dum_vector;
       for (i = elem_begin; i != poly_begin; ++i) {
-        tool->tree_stats().leaf_object_tests()++;
+        tool->tree_stats().leafObjectTests++;
         rval = moab->get_connectivity( *i, conn, count, true, &dum_vector);
         if (MB_SUCCESS != rval) 
           return rval;
@@ -904,7 +909,7 @@ namespace moab {
   
         // polyhedra
       for (i = poly_begin; i != set_begin; ++i) {
-        tool->tree_stats().leaf_object_tests()++;
+        tool->tree_stats().leafObjectTests++;
         rval = moab->get_connectivity( *i, conn, count, true );
         if (MB_SUCCESS != rval) 
           return rval;
@@ -938,7 +943,7 @@ namespace moab {
         // sets
       BoundBox tbox;
       for (i = set_begin; i != elems.end(); ++i) {
-        tool->tree_stats().leaf_object_tests()++;
+        tool->tree_stats().leafObjectTests++;
         rval = tbox.update(*tool->moab(), *i);
         if (MB_SUCCESS != rval)
           return rval;
@@ -1300,6 +1305,8 @@ namespace moab {
       std::vector<EntityHandle> children;
       Plane plane;
 
+      treeStats.numTraversals++;
+      
         // kdtrees never have multiple leaves containing a pt
       if (multiple_leaves) *multiple_leaves = false;
       
@@ -1307,7 +1314,11 @@ namespace moab {
       ErrorCode rval = moab()->get_child_meshsets( node, children );
       if (MB_SUCCESS != rval)
         return rval;
+      treeStats.nodesVisited++;
+
       while (!children.empty()) {
+        treeStats.nodesVisited++;
+        
         rval = get_split_plane( node, plane );
         if (MB_SUCCESS != rval)
           return rval;
@@ -1320,6 +1331,7 @@ namespace moab {
         if (MB_SUCCESS != rval)
           return rval;
       }
+      treeStats.leavesVisited++;
       leaf_out = node;
 
       return MB_SUCCESS;
@@ -1331,18 +1343,21 @@ namespace moab {
                                            EntityHandle *start_node)
     {
       ErrorCode rval;
+      treeStats.numTraversals++;
     
         // kdtrees never have multiple leaves containing a pt
       if (multiple_leaves) *multiple_leaves = false;
 
       leaf_it.mBox[0] = boundBox.bMin;
       leaf_it.mBox[1] = boundBox.bMax;
-      
+
         // test that point is inside tree
       if (point[0] < boundBox.bMin[0] || point[0] > boundBox.bMax[0] ||
           point[1] < boundBox.bMin[1] || point[1] > boundBox.bMax[1] ||
-          point[2] < boundBox.bMin[2] || point[2] > boundBox.bMax[2])
-        return MB_ENTITY_NOT_FOUND;  
+          point[2] < boundBox.bMin[2] || point[2] > boundBox.bMax[2]) {
+        treeStats.nodesVisited++;
+        return MB_ENTITY_NOT_FOUND;
+      }
 
         // initialize iterator at tree root
       leaf_it.treeTool = this;
@@ -1352,6 +1367,8 @@ namespace moab {
         // loop until we reach a leaf
       AdaptiveKDTree::Plane plane;
       for(;;) {
+        treeStats.nodesVisited++;
+        
           // get children
         leaf_it.childVect.clear();
         rval = moab()->get_child_meshsets( leaf_it.handle(), leaf_it.childVect );
@@ -1359,8 +1376,10 @@ namespace moab {
           return rval;
       
           // if no children, then at leaf (done)
-        if (leaf_it.childVect.empty())
+        if (leaf_it.childVect.empty()) {
+          treeStats.leavesVisited++;
           break;
+        }
 
           // get split plane
         rval = get_split_plane( leaf_it.handle(), plane );
@@ -1389,6 +1408,7 @@ namespace moab {
                                               std::vector<double> *result_dists,
                                               EntityHandle *tree_root)
     {
+      treeStats.numTraversals++;
       const double dist_sqr = distance * distance;
       const CartVect from(from_point);
       std::vector<NodeDistance> list, result_list_nodes;     // list of subtrees to traverse, and results 
@@ -1415,8 +1435,10 @@ namespace moab {
           else if (from_point[i] > box.bMax[i])
             node.dist[i] = from_point[i] - box.bMax[i];
         }
-        if (node.dist % node.dist > dist_sqr)
+        if (node.dist % node.dist > dist_sqr) {
+          treeStats.nodesVisited++;
           return MB_SUCCESS;
+        }
       }
   
         // begin with root in list  
@@ -1427,12 +1449,14 @@ namespace moab {
 
         node = list.back();
         list.pop_back();
+        treeStats.nodesVisited++;
       
           // If leaf node, test contained triangles
         children.clear();
         rval = moab()->get_child_meshsets( node.handle, children );
         if (children.empty()) {
           result_list_nodes.push_back( node);
+          treeStats.leavesVisited++;
           continue;
         }
       
@@ -2008,5 +2032,137 @@ namespace moab {
       unsigned min_depth;
       return compute_depth( root, min_depth, dep );
     }
+
+    static std::string mem_to_string( unsigned long mem )
+    {
+      char unit[3] = "B";
+      if (mem > 9*1024) {
+        mem = (mem + 512) / 1024;
+        strcpy( unit, "kB" );
+      }
+      if (mem > 9*1024) {
+        mem = (mem + 512) / 1024;
+        strcpy( unit, "MB" );
+      }
+      if (mem > 9*1024) {
+        mem = (mem + 512) / 1024;
+        strcpy( unit, "GB" );
+      }
+      char buffer[256];
+      sprintf(buffer, "%lu %s", mem, unit );
+      return buffer;
+    }
+
+    template <typename T> 
+    struct SimpleStat 
+    {
+      T min, max, sum, sqr;
+      size_t count;
+      SimpleStat();
+      void add( T value );
+      double avg() const { return (double)sum / count; }
+      double rms() const { return sqrt( (double)sqr / count ); }
+      double dev() const { return (count > 1 ? sqrt( (count * (double)sqr - (double)sum * (double)sum) / ((double)count * (count - 1) ) ) : 0.0); }
+    };
+
+    template <typename T> SimpleStat<T>::SimpleStat()
+            : min(  std::numeric_limits<T>::max() ),
+              max(  std::numeric_limits<T>::min() ),
+              sum( 0 ), sqr( 0 ), count( 0 )
+    {}
+
+    template <typename T> void SimpleStat<T>::add( T value )
+    {
+      if (value < min)
+        min = value;
+      if (value > max)
+        max = value;
+      sum += value;
+      sqr += value*value;
+      ++count;
+    }
+  
+    ErrorCode AdaptiveKDTree::print() 
+    {
+      Range range;
+
+      Range tree_sets, elem2d, elem3d, verts, all;
+      moab()->get_child_meshsets( myRoot, tree_sets, 0 );
+      for (Range::iterator rit = tree_sets.begin(); rit != tree_sets.end(); rit++) {
+        moab()->get_entities_by_dimension( *rit, 2, elem2d );
+        moab()->get_entities_by_dimension( *rit, 3, elem3d );
+        moab()->get_entities_by_type( *rit, MBVERTEX, verts );
+      }
+      all.merge( verts );
+      all.merge( elem2d );
+      all.merge( elem3d );
+      tree_sets.insert( myRoot );
+      unsigned long set_used, set_amortized, set_store_used, set_store_amortized,
+          set_tag_used, set_tag_amortized, elem_used, elem_amortized;
+      moab()->estimated_memory_use( tree_sets, 
+                                       &set_used, &set_amortized, 
+                                       &set_store_used, &set_store_amortized,
+                                       0, 0, 0, 0,
+                                       &set_tag_used, &set_tag_amortized );
+      moab()->estimated_memory_use( all,  &elem_used, &elem_amortized );
+  
+      int num_2d = 0, num_3d = 0;;
+      moab()->get_number_entities_by_dimension( 0, 2, num_2d );
+      moab()->get_number_entities_by_dimension( 0, 3, num_3d );
+  
+      BoundBox box;
+      ErrorCode rval = get_bounding_box(box, &myRoot );
+      if (MB_SUCCESS != rval || box == BoundBox()) throw rval;
+      double diff[3] = { box.bMax[0]-box.bMin[0], box.bMax[1]-box.bMin[1], box.bMax[2] - box.bMin[2] };
+      double tree_vol = diff[0]*diff[1]*diff[2];
+      double tree_surf_area = 2*(diff[0]*diff[1] + diff[1]*diff[2] + diff[2]*diff[0]);
+  
+      SimpleStat<unsigned> depth, size;
+      SimpleStat<double> vol, surf;
   
+      AdaptiveKDTreeIter iter;
+      get_tree_iterator( myRoot, iter );
+      do {
+        depth.add( iter.depth() );
+    
+        int num_leaf_elem;
+        moab()->get_number_entities_by_handle( iter.handle(), num_leaf_elem );
+        size.add(num_leaf_elem);
+    
+        const double* n = iter.box_min();
+        const double* x = iter.box_max();
+        double dims[3] = {x[0]-n[0], x[1]-n[1], x[2]-n[2]};
+    
+        double leaf_vol = dims[0]*dims[1]*dims[2];
+        vol.add(leaf_vol);
+    
+        double area = 2.0*(dims[0]*dims[1] + dims[1]*dims[2] + dims[2]*dims[0]);
+        surf.add(area);
+    
+      } while (MB_SUCCESS == iter.step());
+  
+      printf("------------------------------------------------------------------\n");
+      printf("tree volume:      %f\n", tree_vol );
+      printf("total elements:   %d\n", num_2d + num_3d );
+      printf("number of leaves: %lu\n", (unsigned long)depth.count );
+      printf("number of nodes:  %lu\n", (unsigned long)tree_sets.size() );
+      printf("volume ratio:     %0.2f%%\n", 100*(vol.sum / tree_vol));
+      printf("surface ratio:    %0.2f%%\n", 100*(surf.sum / tree_surf_area));
+      printf("\nmemory:           used  amortized\n");
+      printf("            ---------- ----------\n");
+      printf("elements    %10s %10s\n",mem_to_string(elem_used).c_str(), mem_to_string(elem_amortized).c_str());
+      printf("sets (total)%10s %10s\n",mem_to_string(set_used).c_str(), mem_to_string(set_amortized).c_str());
+      printf("sets        %10s %10s\n",mem_to_string(set_store_used).c_str(), mem_to_string(set_store_amortized).c_str());
+      printf("set tags    %10s %10s\n",mem_to_string(set_tag_used).c_str(), mem_to_string(set_tag_amortized).c_str());
+      printf("\nleaf stats:        min        avg        rms        max    std.dev\n");
+      printf("            ---------- ---------- ---------- ---------- ----------\n");
+      printf("depth       %10u %10.1f %10.1f %10u %10.2f\n", depth.min, depth.avg(), depth.rms(), depth.max, depth.dev() );
+      printf("triangles   %10u %10.1f %10.1f %10u %10.2f\n", size.min, size.avg(), size.rms(), size.max, size.dev() );
+      printf("volume      %10.2g %10.2g %10.2g %10.2g %10.2g\n", vol.min, vol.avg(), vol.rms(), vol.max, vol.dev() );
+      printf("surf. area  %10.2g %10.2g %10.2g %10.2g %10.2g\n", surf.min, surf.avg(), surf.rms(), surf.max, surf.dev() );
+      printf("------------------------------------------------------------------\n");
+
+      return MB_SUCCESS;
+    }
+
 } // namespace moab

diff --git a/src/BVHTree.cpp b/src/BVHTree.cpp
index f175414..cc582c8 100644
--- a/src/BVHTree.cpp
+++ b/src/BVHTree.cpp
@@ -80,6 +80,9 @@ namespace moab
       rval = convert_tree(tree_nodes);
       if (MB_SUCCESS != rval) return rval;
 
+      treeStats.reset();
+      rval = treeStats.compute_stats(mbImpl, startSetHandle);
+      
       return rval;
     }
 
@@ -428,18 +431,22 @@ namespace moab
     ErrorCode BVHTree::find_point(const std::vector<double> &point, 
                                   const unsigned int &index,
                                   const double tol,
-                                  std::pair<EntityHandle, CartVect> &result) const 
+                                  std::pair<EntityHandle, CartVect> &result)
     {
+      if (index == 0) treeStats.numTraversals++;
       const TreeNode &node = myTree[index];
+      treeStats.nodesVisited++;
       CartVect params;
       bool is_inside;
       ErrorCode rval = MB_SUCCESS;
       if(node.dim == 3){
+        treeStats.leavesVisited++;
         Range entities;
         rval = mbImpl->get_entities_by_handle(startSetHandle+index, entities);
         if (MB_SUCCESS != rval) return rval;
         
         for(Range::iterator i = entities.begin(); i != entities.end(); i++) {
+          treeStats.leafObjectTests++;
           myEval->set_ent_handle(*i);
           myEval->reverse_eval(&point[0], tol, params.array(), &is_inside);
           if (is_inside) {
@@ -496,16 +503,19 @@ namespace moab
       return MB_SUCCESS;
     }
 
-    EntityHandle BVHTree::bruteforce_find(const double *point, const double tol) const {
+    EntityHandle BVHTree::bruteforce_find(const double *point, const double tol) {
+      treeStats.numTraversals++;
       CartVect params;
       bool is_inside;
       for(unsigned int i = 0; i < myTree.size(); i++) {
         if(myTree[i].dim != 3 || !myTree[i].box.contains_point(point, tol)) continue;
         if (myEval) {
+          treeStats.leavesVisited++;
           Range entities;
           ErrorCode rval = mbImpl->get_entities_by_handle(startSetHandle+i, entities);
           if (MB_SUCCESS != rval) return 0;
           for(Range::iterator j = entities.begin(); j != entities.end(); ++j) {
+            treeStats.leafObjectTests++;
             myEval->set_ent_handle(*j);
             myEval->reverse_eval(point, tol, params.array(), &is_inside);
             if (is_inside) return *j;
@@ -536,6 +546,8 @@ namespace moab
     {
       std::vector<EntityHandle> children;
 
+      treeStats.numTraversals++;
+
       EntityHandle this_set = (start_node ? *start_node : startSetHandle);
         // convoluted check because the root is different from startSetHandle
       if (this_set != myRoot &&
@@ -549,6 +561,8 @@ namespace moab
       BoundBox box;
       while( !candidates.empty() ) {
         EntityHandle ind = candidates.back();
+        treeStats.nodesVisited++;
+        if (myTree[ind].dim == 3) treeStats.leavesVisited++;
         this_set = startSetHandle + ind;
         candidates.pop_back();
 
@@ -587,6 +601,8 @@ namespace moab
         return MB_FAILURE;
       else if (this_set == myRoot) this_set = startSetHandle;
 
+      treeStats.numTraversals++;
+
       const double dist_sqr = distance * distance;
       const CartVect from(from_point);
       std::vector<EntityHandle> candidates, result_list_nodes;     // list of subtrees to traverse, and results 
@@ -605,6 +621,8 @@ namespace moab
         EntityHandle ind = candidates.back();
         this_set = startSetHandle + ind;
         candidates.pop_back();
+        treeStats.nodesVisited++;
+        if (myTree[ind].dim == 3) treeStats.leavesVisited++;
 
           // test box of this node
         rval = get_bounding_box(box, &this_set);
@@ -639,6 +657,17 @@ namespace moab
       return MB_SUCCESS;
     }
       
+    ErrorCode BVHTree::print()
+    {
+      int i;
+      std::vector<TreeNode>::iterator it;
+      for (it = myTree.begin(), i = 0; it != myTree.end(); it++, i++) {
+        std::cout << "Node " << i << ": dim = " << it->dim << ", child = " << it->child << ", Lmax/Rmin = "
+                  << it->Lmax << "/" << it->Rmin << ", box = " << it->box << std::endl;
+      }
+      return MB_SUCCESS;
+    }
+      
       
 } // namespace moab
 

diff --git a/src/Tree.cpp b/src/Tree.cpp
index d098291..22d85ea 100644
--- a/src/Tree.cpp
+++ b/src/Tree.cpp
@@ -44,7 +44,18 @@ namespace moab
 
     ErrorCode Tree::find_all_trees( Range& results )
     {
-      return moab()->get_entities_by_type_and_tag( 0, MBENTITYSET, &boxTag, 0, 1, results );
+      Tag tag = get_box_tag();
+      ErrorCode rval = moab()->get_entities_by_type_and_tag( 0, MBENTITYSET, &tag, 0, 1, results );
+      if (MB_SUCCESS != rval || results.empty()) return rval;
+      std::vector<BoundBox> boxes(results.size());
+      rval = moab()->tag_get_data(tag, results, &boxes[0]);
+      if (MB_SUCCESS != rval) return rval;
+      for (std::vector<BoundBox>::iterator vit = boxes.begin(); vit != boxes.end(); vit++)
+        boundBox.update(*vit);
+
+      if (results.size() == 1) myRoot = *results.begin();
+      
+      return MB_SUCCESS;
     }
 
     ErrorCode Tree::create_root( const double box_min[3],

diff --git a/src/moab/AdaptiveKDTree.hpp b/src/moab/AdaptiveKDTree.hpp
index d2dfe2f..4f1f398 100644
--- a/src/moab/AdaptiveKDTree.hpp
+++ b/src/moab/AdaptiveKDTree.hpp
@@ -229,6 +229,9 @@ namespace moab {
           VERTEX_SAMPLE // = 3
       };
   
+        //! print various things about this tree
+      virtual ErrorCode print();
+      
   private:
 
       friend class AdaptiveKDTreeIter;

diff --git a/src/moab/BVHTree.hpp b/src/moab/BVHTree.hpp
index b56c456..b1eceab 100644
--- a/src/moab/BVHTree.hpp
+++ b/src/moab/BVHTree.hpp
@@ -99,6 +99,10 @@ namespace moab {
                                         std::vector<EntityHandle>& result_list,
                                         std::vector<double> *result_dists,
                                         EntityHandle *tree_root);
+
+        //! print various things about this tree
+      virtual ErrorCode print();
+      
   private:
         // don't allow copy constructor, too complicated
       BVHTree(const BVHTree &s);
@@ -228,9 +232,9 @@ namespace moab {
       ErrorCode find_point(const std::vector<double> &point, 
                            const unsigned int &index,
                            const double tol,
-                           std::pair<EntityHandle, CartVect> &result) const;
+                           std::pair<EntityHandle, CartVect> &result);
       
-      EntityHandle bruteforce_find(const double *point, const double tol) const;
+      EntityHandle bruteforce_find(const double *point, const double tol);
 
       int local_build_tree(std::vector<Node> &tree_nodes,
                            HandleDataVec::iterator begin, 

diff --git a/src/moab/BoundBox.hpp b/src/moab/BoundBox.hpp
index 0cf543a..51f229e 100644
--- a/src/moab/BoundBox.hpp
+++ b/src/moab/BoundBox.hpp
@@ -51,6 +51,9 @@ namespace moab {
         bMax = from.bMax;
         return *this;
       }
+      inline bool operator==(const BoundBox &box) const {
+        return (bMin == box.bMin && bMax == box.bMax);
+      }
 
       CartVect bMin, bMax;
     };

diff --git a/src/moab/CartVect.hpp b/src/moab/CartVect.hpp
index b1d9948..a249fef 100644
--- a/src/moab/CartVect.hpp
+++ b/src/moab/CartVect.hpp
@@ -50,6 +50,8 @@ class CartVect
       { d[0] *= s; d[1] *= s; d[2] *= s; return *this; }
     inline CartVect& operator/=( double s )
       { d[0] /= s; d[1] /= s; d[2] /= s; return *this; }
+  inline bool operator==(const CartVect& v ) const
+      { return d[0] == v[0] && d[1] == v[1] && d[2] == v[2]; }
 
     inline double length() const; //!< vector length
 

diff --git a/src/moab/Tree.hpp b/src/moab/Tree.hpp
index c18c147..2ff1f63 100644
--- a/src/moab/Tree.hpp
+++ b/src/moab/Tree.hpp
@@ -150,6 +150,9 @@ namespace moab {
       ErrorCode create_root( const double box_min[3], const double box_max[3],
                              EntityHandle& root_handle);
       
+        //! print various things about this tree
+      virtual ErrorCode print() = 0;
+      
   protected:
 
         /** \brief Parse options common to all trees

diff --git a/src/moab/TreeStats.hpp b/src/moab/TreeStats.hpp
index 86dd79f..738aae9 100644
--- a/src/moab/TreeStats.hpp
+++ b/src/moab/TreeStats.hpp
@@ -15,6 +15,8 @@
 #ifndef TREESTATS_HPP
 #define TREESTATS_HPP
 
+#include "moab/Interface.hpp"
+
 #include <vector>
 #include <iostream>
 #include <string>
@@ -24,58 +26,79 @@ namespace moab
     class TreeStats{
   public:
         //! constructor
-      TreeStats() 
-              : leafObjectTests(0) 
-          {}      
-      
-        //! return counts of nodes visited, indexed by tree depth.  
-        //! the counts include both leaves and interior nodes
-      const unsigned int &nodes_visited() const
-          {return nodesVisited;}
-
-        //! return counts of tree leaves visited, indexed by tree depth
-      const unsigned int &leaves_visited() const
-          {return leavesVisited;}
-
-        //! return counts of traversals ended, indexed by tree depth
-      const unsigned int &num_traversals() const 
-          {return numTraversals;}
-
-        //! return counts of nodes visited, indexed by tree depth.  
-        //! the counts include both leaves and interior nodes
-      unsigned int &nodes_visited() 
-          {return nodesVisited;}
-
-        //! return counts of tree leaves visited, indexed by tree depth
-      unsigned int &leaves_visited()
-          {return leavesVisited;}
-
-        //! return counts of traversals ended, indexed by tree depth
-      unsigned int &num_traversals()
-          {return numTraversals;}
+      TreeStats() {reset();}
 
-        //! return total number of leaf-object tests (ray-triangle, point in elem, etc.) performed
-      const unsigned int &leaf_object_tests() const
-          {return leafObjectTests;}
-
-      unsigned int &leaf_object_tests()
-          {return leafObjectTests;}
-
-        //! reset all counters on this structure
+        /** \brief Given a root node, compute the stats for a tree 
+         * \param impl MOAB instance pointer
+         * \param root_node Root entity set for the tree
+         */
+      ErrorCode compute_stats(Interface *impl, EntityHandle root_node);
+      
+        //! reset traversal counters
+      void reset_trav_stats();
+              
+        //! reset all counters
       void reset();
               
         //! print the contents of this structure to given stream
       void print() const ;
 
-  private:
+        // tree stats that depend only on structure (not traversal)
+      unsigned int maxDepth;
+      unsigned int numNodes;
+      unsigned int numLeaves;
+
+        // traversal statistics
       unsigned int nodesVisited;
       unsigned int leavesVisited;
       unsigned int numTraversals;
       unsigned int leafObjectTests;
+
+  private:
+      ErrorCode traverse(Interface *impl, EntityHandle node, unsigned int &depth);
+      
     };
 
+    inline ErrorCode TreeStats::compute_stats(Interface *impl, EntityHandle root_node) 
+    {
+      maxDepth = 0;
+      return traverse(impl, root_node, maxDepth);
+    }
+      
+    inline ErrorCode TreeStats::traverse(Interface *impl, EntityHandle node, unsigned int &depth) 
+    {
+      depth++;
+      numNodes++;
+      std::vector<EntityHandle> children;
+      children.reserve(2);
+      ErrorCode rval = impl->get_child_meshsets(node, children);
+      if (MB_SUCCESS != rval) return rval;
+      if (children.empty()) {
+        numLeaves++;
+        return MB_SUCCESS;
+      }
+      else {
+        unsigned int right_depth = depth, left_depth = depth;
+        rval = traverse(impl, children[0], left_depth);
+        if (MB_SUCCESS != rval) return rval;
+        rval = traverse(impl, children[1], right_depth);
+        if (MB_SUCCESS != rval) return rval;
+        depth = std::max(left_depth, right_depth);
+        return MB_SUCCESS;
+      }
+    }
+
     inline void TreeStats::reset()
     {
+      maxDepth = 0;
+      numNodes = 0;
+      numLeaves = 0;
+      
+      reset_trav_stats();
+    }
+    
+    inline void TreeStats::reset_trav_stats() 
+    {
       nodesVisited = 0;
       leavesVisited = 0;
       numTraversals = 0;

diff --git a/test/kd_tree_tool.cpp b/test/kd_tree_tool.cpp
index 8f7a3b5..005dfc1 100644
--- a/test/kd_tree_tool.cpp
+++ b/test/kd_tree_tool.cpp
@@ -62,6 +62,7 @@ static void usage( bool err = true )
   exit( err );
 }
 
+/*
 #if !defined(_MSC_VER) && !defined(__MINGW32__)
 static void memory_use( unsigned long& vsize, unsigned long& rss )
 {
@@ -87,6 +88,7 @@ static void memory_use( unsigned long& vsize, unsigned long& rss )
 static void memory_use( unsigned long& vsize, unsigned long& rss )
   { vsize = rss = 0; }
 #endif
+*/
 
 static int parseint( int& i, int argc, char* argv[] )
 {
@@ -189,6 +191,9 @@ int main( int argc, char* argv[] )
       default: usage();
     }
   }
+
+    // this test relies on not cleaning up trees
+  options << "CLEAN_UP=false;";
   
   if (make_grid != !output_file)
     usage();
@@ -242,7 +247,18 @@ int main( int argc, char* argv[] )
   }
   
   std::cout << "Calculating stats..." << std::endl;
-  print_stats( interface );
+  AdaptiveKDTree tool(interface);
+  Range range;
+  tool.find_all_trees( range );
+  if (range.size() != 1) {
+    if (range.empty())
+      std::cerr << "Internal error: Failed to retreive tree." << std::endl;
+    else
+      std::cerr << "Internal error: Multiple tree roots." << std::endl;
+    exit(5);
+  }
+  tool.print();
+
   stat_time = clock() - build_time;
   
   if (tag_elems) {
@@ -385,155 +401,6 @@ std::string clock_to_string( clock_t t )
   return buffer;
 }
 
-std::string mem_to_string( unsigned long mem )
-{
-  char unit[3] = "B";
-  if (mem > 9*1024) {
-    mem = (mem + 512) / 1024;
-    strcpy( unit, "kB" );
-  }
-  if (mem > 9*1024) {
-    mem = (mem + 512) / 1024;
-    strcpy( unit, "MB" );
-  }
-  if (mem > 9*1024) {
-    mem = (mem + 512) / 1024;
-    strcpy( unit, "GB" );
-  }
-  char buffer[256];
-  sprintf(buffer, "%lu %s", mem, unit );
-  return buffer;
-}
-
-template <typename T> 
-struct SimpleStat 
-{
-  T min, max, sum, sqr;
-  size_t count;
-  SimpleStat();
-  void add( T value );
-  double avg() const { return (double)sum / count; }
-  double rms() const { return sqrt( (double)sqr / count ); }
-  double dev() const { return sqrt( (count * (double)sqr - (double)sum * (double)sum) / ((double)count * (count - 1) ) ); }
-};
-
-template <typename T> SimpleStat<T>::SimpleStat()
-  : min(  std::numeric_limits<T>::max() ),
-    max(  std::numeric_limits<T>::min() ),
-    sum( 0 ), sqr( 0 ), count( 0 )
-  {}
-
-template <typename T> void SimpleStat<T>::add( T value )
-{
-  if (value < min)
-    min = value;
-  if (value > max)
-    max = value;
-  sum += value;
-  sqr += value*value;
-  ++count;
-}
-  
-void print_stats( Interface* interface )
-{
-  EntityHandle root;
-  Range range;
-  AdaptiveKDTree tool(interface);
-  
-  tool.find_all_trees( range );
-  if (range.size() != 1) {
-    if (range.empty())
-      std::cerr << "Internal error: Failed to retreive tree." << std::endl;
-    else
-      std::cerr << "Internal error: Multiple tree roots." << std::endl;
-    exit(5);
-  }
-  
-  root = *range.begin();
-  range.clear();
-
-  Range tree_sets, elem2d, elem3d, verts, all;
-  //interface->get_child_meshsets( root, tree_sets, 0 );
-  interface->get_entities_by_type( 0, MBENTITYSET, tree_sets );
-  tree_sets.erase( tree_sets.begin(), Range::lower_bound( tree_sets.begin(), tree_sets.end(), root ) );
-  interface->get_entities_by_dimension( 0, 2, elem2d );
-  interface->get_entities_by_dimension( 0, 3, elem3d );
-  interface->get_entities_by_type( 0, MBVERTEX, verts );
-  all.clear();
-  all.merge( verts );
-  all.merge( elem2d );
-  all.merge( elem3d );
-  tree_sets.insert( root );
-  unsigned long set_used, set_amortized, set_store_used, set_store_amortized,
-                set_tag_used, set_tag_amortized, elem_used, elem_amortized;
-  interface->estimated_memory_use( tree_sets, 
-                                   &set_used, &set_amortized, 
-                                   &set_store_used, &set_store_amortized,
-                                   0, 0, 0, 0,
-                                   &set_tag_used, &set_tag_amortized );
-  interface->estimated_memory_use( all,  &elem_used, &elem_amortized );
-  
-  int num_2d = 0, num_3d = 0;;
-  interface->get_number_entities_by_dimension( 0, 2, num_2d );
-  interface->get_number_entities_by_dimension( 0, 3, num_3d );
-  
-  BoundBox box;
-  tool.get_bounding_box(box, &root );
-  double diff[3] = { box.bMax[0]-box.bMin[0], box.bMax[1]-box.bMin[1], box.bMax[2] - box.bMin[2] };
-  double tree_vol = diff[0]*diff[1]*diff[2];
-  double tree_surf_area = 2*(diff[0]*diff[1] + diff[1]*diff[2] + diff[2]*diff[0]);
-  
-  SimpleStat<unsigned> depth, size;
-  SimpleStat<double> vol, surf;
-  
-  AdaptiveKDTreeIter iter;
-  tool.get_tree_iterator( root, iter );
-  do {
-    depth.add( iter.depth() );
-    
-    int num_leaf_elem;
-    interface->get_number_entities_by_handle( iter.handle(), num_leaf_elem );
-    size.add(num_leaf_elem);
-    
-    const double* n = iter.box_min();
-    const double* x = iter.box_max();
-    double dims[3] = {x[0]-n[0], x[1]-n[1], x[2]-n[2]};
-    
-    double leaf_vol = dims[0]*dims[1]*dims[2];
-    vol.add(leaf_vol);
-    
-    double area = 2.0*(dims[0]*dims[1] + dims[1]*dims[2] + dims[2]*dims[0]);
-    surf.add(area);
-    
-  } while (MB_SUCCESS == iter.step());
-  
-  unsigned long real_rss, real_vsize;
-  memory_use( real_vsize, real_rss );
-  
-  printf("------------------------------------------------------------------\n");
-  printf("tree volume:      %f\n", tree_vol );
-  printf("total elements:   %d\n", num_2d + num_3d );
-  printf("number of leaves: %lu\n", (unsigned long)depth.count );
-  printf("number of nodes:  %lu\n", (unsigned long)tree_sets.size() );
-  printf("volume ratio:     %0.2f%%\n", 100*(vol.sum / tree_vol));
-  printf("surface ratio:    %0.2f%%\n", 100*(surf.sum / tree_surf_area));
-  printf("\nmemory:           used  amortized\n");
-  printf("            ---------- ----------\n");
-  printf("elements    %10s %10s\n",mem_to_string(elem_used).c_str(), mem_to_string(elem_amortized).c_str());
-  printf("sets (total)%10s %10s\n",mem_to_string(set_used).c_str(), mem_to_string(set_amortized).c_str());
-  printf("sets        %10s %10s\n",mem_to_string(set_store_used).c_str(), mem_to_string(set_store_amortized).c_str());
-  printf("set tags    %10s %10s\n",mem_to_string(set_tag_used).c_str(), mem_to_string(set_tag_amortized).c_str());
-  printf("total real  %10s %10s\n",mem_to_string(real_rss).c_str(), mem_to_string(real_vsize).c_str());
-  printf("\nleaf stats:        min        avg        rms        max    std.dev\n");
-  printf("            ---------- ---------- ---------- ---------- ----------\n");
-  printf("depth       %10u %10.1f %10.1f %10u %10.2f\n", depth.min, depth.avg(), depth.rms(), depth.max, depth.dev() );
-  printf("triangles   %10u %10.1f %10.1f %10u %10.2f\n", size.min, size.avg(), size.rms(), size.max, size.dev() );
-  printf("volume      %10.2g %10.2g %10.2g %10.2g %10.2g\n", vol.min, vol.avg(), vol.rms(), vol.max, vol.dev() );
-  printf("surf. area  %10.2g %10.2g %10.2g %10.2g %10.2g\n", surf.min, surf.avg(), surf.rms(), surf.max, surf.dev() );
-  printf("------------------------------------------------------------------\n");
-}
-
-
 static int hash_handle( EntityHandle handle )
 {
   EntityID h = ID_FROM_HANDLE(handle);

diff --git a/test/spatial_locator_test.cpp b/test/spatial_locator_test.cpp
index 9270a49..547f908 100644
--- a/test/spatial_locator_test.cpp
+++ b/test/spatial_locator_test.cpp
@@ -20,8 +20,9 @@ const int npoints = 1000;
 
 void test_kd_tree();
 void test_bvh_tree();
+void test_locator(SpatialLocator *sl);
 
-ErrorCode create_hex_mesh(Interface &mb, Range &elems, int n = 4, int dim = 3);
+ErrorCode create_hex_mesh(Interface &mb, Range &elems, int n = 10, int dim = 3);
 
 int main(int argc, char **argv)
 {
@@ -55,25 +56,8 @@ void test_kd_tree()
 
     // initialize spatial locator with the elements and the default tree type
   SpatialLocator *sl = new SpatialLocator(&mb, elems);
-  CartVect box_del, test_pt, test_res;
-  BoundBox box;
-  rval = sl->get_bounding_box(box); CHECK_ERR(rval);
-  box_del = box.bMax - box.bMin;
-
-  double denom = 1.0 / (double)RAND_MAX;
-  bool is_in;
-  EntityHandle ent;
-  for (int i = 0; i < npoints; i++) {    
-      // generate a small number of random point to test
-    double rx = (double)rand() * denom, ry = (double)rand() * denom, rz = (double)rand() * denom;
-    test_pt = box.bMin + CartVect(rx*box_del[0], ry*box_del[1], rz*box_del[2]);
-
-    // call spatial locator to locate points
-    rval = sl->locate_points(test_pt.array(), 1, &ent, test_res.array(), 0.0, 0.0, &is_in); CHECK_ERR(rval);
 
-    // verify that the point was found
-    CHECK_EQUAL(is_in, true);
-  }
+  test_locator(sl);
 
     // destroy spatial locator, and tree along with it
   delete sl;
@@ -91,9 +75,17 @@ void test_bvh_tree()
     // initialize spatial locator with the elements and a BVH tree
   BVHTree bvh(&mb);
   SpatialLocator *sl = new SpatialLocator(&mb, elems, &bvh);
+  test_locator(sl);
+  
+    // destroy spatial locator, and tree along with it
+  delete sl;
+}
+
+void test_locator(SpatialLocator *sl) 
+{
   CartVect box_del, test_pt, test_res;
   BoundBox box;
-  rval = sl->get_bounding_box(box); CHECK_ERR(rval);
+  ErrorCode rval = sl->get_bounding_box(box); CHECK_ERR(rval);
   box_del = box.bMax - box.bMin;
 
   double denom = 1.0 / (double)RAND_MAX;
@@ -111,8 +103,11 @@ void test_bvh_tree()
     CHECK_EQUAL(is_in, true);
   }
 
-    // destroy spatial locator, and tree along with it
-  delete sl;
+  std::cout << "Traversal stats:" << std::endl;
+  sl->get_tree()->tree_stats().print();
+
+  std::cout << "Tree information: " << std::endl;
+  rval = sl->get_tree()->print();
 }
 
 ErrorCode create_hex_mesh(Interface &mb, Range &elems, int n, int dim) 


https://bitbucket.org/fathomteam/moab/commits/60907bc18926/
Changeset:   60907bc18926
Branch:      None
User:        tautges
Date:        2013-05-24 18:58:32
Summary:     - changing SplitData::myDim to a double, which it is meant to be
- improving BoundBox::operator<<
- removing check that right bbox encloses split bbox, the latter is the whole box, and right child is by definition smaller

Affected #:  3 files

diff --git a/src/BVHTree.cpp b/src/BVHTree.cpp
index cc582c8..3aa5076 100644
--- a/src/BVHTree.cpp
+++ b/src/BVHTree.cpp
@@ -284,15 +284,14 @@ namespace moab
       BoundBox test_box(data.rightBox);
       if(!data.boundingBox.contains_box(test_box)) {
         std::cerr << "MEDIAN: BB Does not contain splits" << std::endl;
-      }
-      if(!test_box.contains_box(data.boundingBox)) {
-        std::cerr << "MEDIAN: splits do not contain BB" << std::endl;
+        std::cerr << "test_box:         " << test_box << std::endl;
+        std::cerr << "data.boundingBox: " << data.boundingBox << std::endl;
       }
 #endif
     }
 
     void BVHTree::find_split(HandleDataVec::iterator &begin, 
-                             HandleDataVec::iterator &end, 
+                             HandleDataVec::iterator &end,
                              SplitData &data) const
     {
       std::vector<std::vector<Bucket> > buckets(3, std::vector<Bucket>(splitsPerDir+1) );

diff --git a/src/moab/BVHTree.hpp b/src/moab/BVHTree.hpp
index b1eceab..2d472a0 100644
--- a/src/moab/BVHTree.hpp
+++ b/src/moab/BVHTree.hpp
@@ -110,11 +110,11 @@ namespace moab {
       class HandleData 
       {
     public:
-        HandleData(EntityHandle h, const BoundBox &bx, const int dp) : myHandle(h), myBox(bx), myDim(dp) {}
+        HandleData(EntityHandle h, const BoundBox &bx, const double dp) : myHandle(h), myBox(bx), myDim(dp) {}
         HandleData() : myHandle(0), myDim(-1) {}
         EntityHandle myHandle;
         BoundBox myBox;
-        int myDim;
+        double myDim;
       };
       typedef std::vector<HandleData> HandleDataVec;
     

diff --git a/src/moab/BoundBox.hpp b/src/moab/BoundBox.hpp
index 51f229e..5b846bb 100644
--- a/src/moab/BoundBox.hpp
+++ b/src/moab/BoundBox.hpp
@@ -128,10 +128,10 @@ namespace moab {
     }
 
     inline std::ostream &operator<<(std::ostream& out, const BoundBox &box) {
-      out << "Max: ";
-      out << box.bMax;
       out << "Min: ";
       out << box.bMin;
+      out << ", Max: ";
+      out << box.bMax;
       return out;
     }
 


https://bitbucket.org/fathomteam/moab/commits/b1a7dd991855/
Changeset:   b1a7dd991855
Branch:      None
User:        tautges
Date:        2013-05-29 17:34:15
Summary:     Adding handling for element evaluation to the trees.  This can make searching faster in some cases,
esp. for BVH trees where a point can be in multiple leaves.

Affected #:  15 files

diff --git a/src/AdaptiveKDTree.cpp b/src/AdaptiveKDTree.cpp
index ecb8cb2..6ceebc6 100644
--- a/src/AdaptiveKDTree.cpp
+++ b/src/AdaptiveKDTree.cpp
@@ -5,6 +5,7 @@
 #include "moab/Interface.hpp"
 #include "moab/GeomUtil.hpp"
 #include "moab/Range.hpp"
+#include "moab/ElemEvaluator.hpp"
 #include "Internals.hpp"
 #include <math.h>
 
@@ -1299,22 +1300,30 @@ namespace moab {
 
     ErrorCode AdaptiveKDTree::point_search(const double *point,
                                            EntityHandle& leaf_out,
+                                           double tol,
                                            bool *multiple_leaves,
-                                           EntityHandle *start_node)
+                                           EntityHandle *start_node,
+                                           CartVect *params)
     {
       std::vector<EntityHandle> children;
       Plane plane;
 
       treeStats.numTraversals++;
-      
+      leaf_out = 0;
+      BoundBox box;
         // kdtrees never have multiple leaves containing a pt
       if (multiple_leaves) *multiple_leaves = false;
       
       EntityHandle node = (start_node ? *start_node : myRoot);
-      ErrorCode rval = moab()->get_child_meshsets( node, children );
+
+      treeStats.nodesVisited++;
+      ErrorCode rval = get_bounding_box(box, &node);
+      if (MB_SUCCESS != rval) return rval;
+      if (!box.contains_point(point, tol)) return MB_SUCCESS;
+      
+      rval = moab()->get_child_meshsets( node, children );
       if (MB_SUCCESS != rval)
         return rval;
-      treeStats.nodesVisited++;
 
       while (!children.empty()) {
         treeStats.nodesVisited++;
@@ -1331,14 +1340,22 @@ namespace moab {
         if (MB_SUCCESS != rval)
           return rval;
       }
+
       treeStats.leavesVisited++;
-      leaf_out = node;
+      if (myEval && params) {
+        rval = myEval->find_containing_entity(node, point, tol,
+                                              leaf_out, params->array(), &treeStats.leafObjectTests);
+        if (MB_SUCCESS != rval) return rval;
+      }
+      else 
+        leaf_out = node;
 
       return MB_SUCCESS;
     }
 
     ErrorCode AdaptiveKDTree::point_search(const double *point,
                                            AdaptiveKDTreeIter& leaf_it,
+                                           double tol,
                                            bool *multiple_leaves,
                                            EntityHandle *start_node)
     {
@@ -1352,9 +1369,7 @@ namespace moab {
       leaf_it.mBox[1] = boundBox.bMax;
 
         // test that point is inside tree
-      if (point[0] < boundBox.bMin[0] || point[0] > boundBox.bMax[0] ||
-          point[1] < boundBox.bMin[1] || point[1] > boundBox.bMax[1] ||
-          point[2] < boundBox.bMin[2] || point[2] > boundBox.bMax[2]) {
+      if (!boundBox.contains_point(point, tol)) {
         treeStats.nodesVisited++;
         return MB_ENTITY_NOT_FOUND;
       }
@@ -1405,7 +1420,9 @@ namespace moab {
     ErrorCode AdaptiveKDTree::distance_search(const double from_point[3],
                                               const double distance,
                                               std::vector<EntityHandle>& result_list,
+                                              double tol,
                                               std::vector<double> *result_dists,
+                                              std::vector<CartVect> *result_params,
                                               EntityHandle *tree_root)
     {
       treeStats.numTraversals++;
@@ -1425,6 +1442,11 @@ namespace moab {
         // (zero if inside box)
       BoundBox box;
       rval = get_bounding_box(box);
+      if (MB_SUCCESS == rval && !box.contains_point(from_point, tol)) {
+        treeStats.nodesVisited++;
+        return MB_SUCCESS;
+      }
+      
         // if bounding box is not available (e.g. not starting from true root)
         // just start with zero.  Less efficient, but will work.
       node.dist = CartVect(0.0);
@@ -1455,9 +1477,23 @@ namespace moab {
         children.clear();
         rval = moab()->get_child_meshsets( node.handle, children );
         if (children.empty()) {
-          result_list_nodes.push_back( node);
           treeStats.leavesVisited++;
-          continue;
+          if (myEval && result_params) {
+            EntityHandle ent;
+            CartVect params;
+            rval = myEval->find_containing_entity(node.handle, from_point, tol,
+                                                  ent, params.array(), &treeStats.leafObjectTests);
+            if (MB_SUCCESS != rval) return rval;
+            else if (ent) {
+              result_list.push_back(ent);
+              result_params->push_back(params);
+              if (result_dists) result_dists->push_back(0.0);
+            }
+          }
+          else {
+            result_list_nodes.push_back( node);
+            continue;
+          }
         }
       
           // If not leaf node, add children to working list
@@ -1499,7 +1535,10 @@ namespace moab {
         }
       }
 
+      if (myEval && result_params) return MB_SUCCESS;
+
         // separate loops to avoid if test inside loop
+      
       result_list.reserve(result_list_nodes.size());
       for (std::vector<NodeDistance>::iterator vit = result_list_nodes.begin(); 
            vit != result_list_nodes.end(); vit++)
@@ -1758,7 +1797,7 @@ namespace moab {
         // the same distance from the input point as the current closest
         // point is.
       CartVect diff = closest_pt - from;
-      rval = distance_search(from_coords, sqrt(diff%diff), leaves, NULL, &tree_root);
+      rval = distance_search(from_coords, sqrt(diff%diff), leaves, 0.0, NULL, NULL, &tree_root);
       if (MB_SUCCESS != rval) return rval;
 
         // Check any close leaves to see if they contain triangles that
@@ -1789,7 +1828,7 @@ namespace moab {
       int conn_len;
 
         // get leaves of tree that intersect sphere
-      rval = distance_search(center, radius, leaves, NULL, &tree_root);
+      rval = distance_search(center, radius, leaves, 0.0, NULL, NULL, &tree_root);
       if (MB_SUCCESS != rval) return rval;
   
         // search each leaf for triangles intersecting sphere

diff --git a/src/BVHTree.cpp b/src/BVHTree.cpp
index 3aa5076..d50f94b 100644
--- a/src/BVHTree.cpp
+++ b/src/BVHTree.cpp
@@ -505,21 +505,17 @@ namespace moab
     EntityHandle BVHTree::bruteforce_find(const double *point, const double tol) {
       treeStats.numTraversals++;
       CartVect params;
-      bool is_inside;
       for(unsigned int i = 0; i < myTree.size(); i++) {
         if(myTree[i].dim != 3 || !myTree[i].box.contains_point(point, tol)) continue;
         if (myEval) {
+          EntityHandle entity = 0;
           treeStats.leavesVisited++;
-          Range entities;
-          ErrorCode rval = mbImpl->get_entities_by_handle(startSetHandle+i, entities);
-          if (MB_SUCCESS != rval) return 0;
-          for(Range::iterator j = entities.begin(); j != entities.end(); ++j) {
-            treeStats.leafObjectTests++;
-            myEval->set_ent_handle(*j);
-            myEval->reverse_eval(point, tol, params.array(), &is_inside);
-            if (is_inside) return *j;
-          }
+          ErrorCode rval = myEval->find_containing_entity(startSetHandle+i, point, tol,
+                                                          entity, params.array(), &treeStats.leafObjectTests);
+          if (entity) return entity;
+          else if (MB_SUCCESS != rval) return 0;
         }
+        else return startSetHandle+i;
       }
       return 0;
     }
@@ -540,8 +536,10 @@ namespace moab
 
     ErrorCode BVHTree::point_search(const double *point,
                                     EntityHandle& leaf_out,
+                                    double tol,
                                     bool *multiple_leaves,
-                                    EntityHandle *start_node) 
+                                    EntityHandle *start_node,
+                                    CartVect *params) 
     {
       std::vector<EntityHandle> children;
 
@@ -568,7 +566,7 @@ namespace moab
           // test box of this node
         ErrorCode rval = get_bounding_box(box, &this_set);
         if (MB_SUCCESS != rval) return rval;
-        if (!box.contains_point(point)) continue;
+        if (!box.contains_point(point, tol)) continue;
 
           // else if not a leaf, test children & put on list
         else if (myTree[ind].dim != 3) {
@@ -576,9 +574,15 @@ namespace moab
           candidates.push_back(myTree[ind].child+1);
           continue;
         }
-      
-          // leaf node within distance; return in list
-        result_list.push_back(this_set);
+        else if (myTree[ind].dim == 3 && myEval && params) {
+          rval = myEval->find_containing_entity(startSetHandle+ind, point, tol,
+                                                leaf_out, params->array(), &treeStats.leafObjectTests);
+          if (leaf_out || MB_SUCCESS != rval) return rval;
+        }
+        else {
+            // leaf node within distance; return in list
+          result_list.push_back(this_set);
+        }
       }
 
       if (!result_list.empty()) leaf_out = result_list[0];
@@ -589,7 +593,9 @@ namespace moab
     ErrorCode BVHTree::distance_search(const double from_point[3],
                                        const double distance,
                                        std::vector<EntityHandle>& result_list,
+                                       double params_tol,
                                        std::vector<double> *result_dists,
+                                       std::vector<CartVect> *result_params,
                                        EntityHandle *tree_root)
     {
         // non-NULL root should be in tree
@@ -637,11 +643,26 @@ namespace moab
           candidates.push_back(myTree[ind].child+1);
           continue;
         }
-      
-          // leaf node within distance; return in list
-        result_list.push_back(this_set);
-        if (result_dists) result_dists->push_back(sqrt(d_sqr));
+
+        if (myEval && result_params) {
+          EntityHandle ent;
+          CartVect params;
+          rval = myEval->find_containing_entity(startSetHandle+ind, from_point, params_tol,
+                                                ent, params.array(), &treeStats.leafObjectTests);
+          if (MB_SUCCESS != rval) return rval;
+          else if (ent) {
+            result_list.push_back(ent);
+            result_params->push_back(params);
+            if (result_dists) result_dists->push_back(0.0);
+          }
+        }
+        else {
+            // leaf node within distance; return in list
+          result_list.push_back(this_set);
+          if (result_dists) result_dists->push_back(sqrt(d_sqr));
+        }
       }
+      
       return MB_SUCCESS;
     }
 

diff --git a/src/LocalDiscretization/ElemEvaluator.cpp b/src/LocalDiscretization/ElemEvaluator.cpp
index 94f544f..45851a8 100644
--- a/src/LocalDiscretization/ElemEvaluator.cpp
+++ b/src/LocalDiscretization/ElemEvaluator.cpp
@@ -99,4 +99,23 @@ namespace moab {
       return MB_NOT_IMPLEMENTED;
     }
       
+    ErrorCode ElemEvaluator::find_containing_entity(Range &entities, const double *point, double tol, 
+                                                    EntityHandle &containing_ent, double *params, 
+                                                    unsigned int *num_evals) 
+    {
+      bool is_inside;
+      ErrorCode rval = MB_SUCCESS;
+      unsigned int nevals = 0;
+      Range::iterator i;
+      for(i = entities.begin(); i != entities.end(); i++) {
+        nevals++;
+        set_ent_handle(*i);
+        rval = reverse_eval(point, tol, params, &is_inside);
+        if (MB_SUCCESS != rval) return rval;
+        if (is_inside) break;
+      }
+      containing_ent = (i == entities.end() ? 0 : *i);
+      if (num_evals) *num_evals += nevals;
+      return MB_SUCCESS;
+    }
 } // namespace moab

diff --git a/src/LocalDiscretization/moab/ElemEvaluator.hpp b/src/LocalDiscretization/moab/ElemEvaluator.hpp
index b73904a..f3be3e9 100644
--- a/src/LocalDiscretization/moab/ElemEvaluator.hpp
+++ b/src/LocalDiscretization/moab/ElemEvaluator.hpp
@@ -156,6 +156,46 @@ namespace moab {
          */
       bool inside(const double *params, const double tol) const;
 
+        /** \brief Given a list of entities, return the entity the point is in, or none
+         * This function reverse-evaluates the entities, returning the first entity containing the point.
+         * If no entity contains the point, containing_ent is returned as 0 and params are unchanged.
+         * This function returns something other than MB_SUCCESS only when queries go wrong for some reason.
+         * num_evals, if non-NULL, is always incremented for each call to reverse_eval.
+         * This function calls set_ent_handle for each entity before calling reverse_eval, so the ElemEvaluator
+         * object is changed.
+         * \param entities Entities tested
+         * \param point Point tested, must have 3 dimensions, even for edge and face entities
+         * \param tol Tolerance for is_inside test
+         * \param containing_ent Entity containing the point, returned 0 if no entity
+         * \param params Parameters of point in containing entity, unchanged if no containing entity
+         * \param num_evals If non-NULL, incremented each time reverse_eval is called
+         * \return Returns non-success only if evaulation failed for some reason (point not in element is NOT a
+         * reason for failure)
+         */
+      ErrorCode find_containing_entity(Range &entities, const double *point, double tol, 
+                                       EntityHandle &containing_ent, double *params, 
+                                       unsigned int *num_evals = NULL);
+      
+        /** \brief Given an entity set, return the contained entity the point is in, or none
+         * This function reverse-evaluates the entities, returning the first entity containing the point.
+         * If no entity contains the point, containing_ent is returned as 0 and params are unchanged.
+         * This function returns something other than MB_SUCCESS only when queries go wrong for some reason.
+         * num_evals, if non-NULL, is always incremented for each call to reverse_eval.
+         * This function calls set_ent_handle for each entity before calling reverse_eval, so the ElemEvaluator
+         * object is changed.
+         * \param ent_set Entity set containing the entities to be tested
+         * \param point Point tested, must have 3 dimensions, even for edge and face entities
+         * \param tol Tolerance for is_inside test
+         * \param containing_ent Entity containing the point, returned 0 if no entity
+         * \param params Parameters of point in containing entity, unchanged if no containing entity
+         * \param num_evals If non-NULL, incremented each time reverse_eval is called
+         * \return Returns non-success only if evaulation failed for some reason (point not in element is NOT a
+         * reason for failure)
+         */
+      ErrorCode find_containing_entity(EntityHandle ent_set, const double *point, double tol, 
+                                       EntityHandle &containing_ent, double *params, 
+                                       unsigned int *num_evals = NULL);
+      
         /** \brief Set the eval set for a given type entity
          * \param tp Entity type for which to set the eval set
          * \param eval_set Eval set object to use
@@ -423,6 +463,17 @@ namespace moab {
                                                workSpace, result);
     }
 
+    inline ErrorCode ElemEvaluator::find_containing_entity(EntityHandle ent_set, const double *point, double tol, 
+                                                           EntityHandle &containing_ent, double *params, 
+                                                           unsigned int *num_evals) 
+    {
+      assert(mbImpl->type_from_handle(ent_set) == MBENTITYSET);
+      Range entities;
+      ErrorCode rval = mbImpl->get_entities_by_handle(ent_set, entities);
+      if (MB_SUCCESS != rval) return rval;
+      else return find_containing_entity(entities, point, tol, containing_ent, params, num_evals);
+    }
+        
     inline bool ElemEvaluator::inside(const double *params, const double tol) const 
     {
       return (*evalSets[entType].insideFcn)(params, entDim, tol);

diff --git a/src/MergeMesh.cpp b/src/MergeMesh.cpp
index d8b6b55..5750b57 100644
--- a/src/MergeMesh.cpp
+++ b/src/MergeMesh.cpp
@@ -171,7 +171,7 @@ moab::ErrorCode MergeMesh::find_merged_to(moab::EntityHandle &tree_root,
       // check close-by leaves too
       leaves_out.clear();
       result = tree.distance_search(from.array(), mergeTol,
-                                    leaves_out, NULL, &tree_root);
+                                    leaves_out, 0.0, NULL, NULL, &tree_root);
       leaf_range2.clear();
       for (std::vector<moab::EntityHandle>::iterator vit = leaves_out.begin();
            vit != leaves_out.end(); vit++) {

diff --git a/src/SpatialLocator.cpp b/src/SpatialLocator.cpp
index ea9cbf3..8397ad7 100644
--- a/src/SpatialLocator.cpp
+++ b/src/SpatialLocator.cpp
@@ -53,7 +53,7 @@ namespace moab
         int i3 = 3*i;
         ents[i] = 0;
         if (abs_eps) {
-          rval = myTree->distance_search(pos+i3, abs_eps, leaves, &dists);
+          rval = myTree->distance_search(pos+i3, abs_eps, leaves, abs_eps, &dists);
           if (MB_SUCCESS != rval) return rval;
           if (!leaves.empty()) {
               // get closest leaf

diff --git a/src/io/ReadNCDF.cpp b/src/io/ReadNCDF.cpp
index 31a2785..c1ffe69 100644
--- a/src/io/ReadNCDF.cpp
+++ b/src/io/ReadNCDF.cpp
@@ -1794,7 +1794,7 @@ ErrorCode ReadNCDF::update(const char *exodus_file_name,
 
       std::vector<EntityHandle> leaves;
       double min_dist = MAX_NODE_DIST;
-      rval = kdtree.distance_search(exo_coords.array(), MAX_NODE_DIST, leaves, NULL, &root);
+      rval = kdtree.distance_search(exo_coords.array(), MAX_NODE_DIST, leaves);
       if(MB_SUCCESS != rval) return rval;
       for(std::vector<EntityHandle>::const_iterator j=leaves.begin(); j!=leaves.end(); ++j) {
 	std::vector<EntityHandle> leaf_verts;

diff --git a/src/moab/AdaptiveKDTree.hpp b/src/moab/AdaptiveKDTree.hpp
index 4f1f398..4a5ce1b 100644
--- a/src/moab/AdaptiveKDTree.hpp
+++ b/src/moab/AdaptiveKDTree.hpp
@@ -68,6 +68,7 @@ namespace moab {
          * containing the point in that case.
          * \param point Point to be located in tree
          * \param leaf_out Leaf containing point
+         * \param tol Tolerance below which a point is "in"
          * \param multiple_leaves Some tree types can have multiple leaves containing a point;
          *          if non-NULL, this parameter is returned true if multiple leaves contain
          *          the input point
@@ -76,8 +77,10 @@ namespace moab {
          */
       virtual ErrorCode point_search(const double *point,
                                      EntityHandle& leaf_out,
+                                     double tol = 0.0,
                                      bool *multiple_leaves = NULL,
-                                     EntityHandle *start_node = NULL);
+                                     EntityHandle *start_node = NULL,
+                                     CartVect *params = NULL);
 
         /** \brief Get leaf containing input position.
          *
@@ -89,6 +92,7 @@ namespace moab {
          * containing the point in that case.
          * \param point Point to be located in tree
          * \param leaf_it Iterator to leaf containing point
+         * \param tol Tolerance below which a point is "in"
          * \param multiple_leaves Some tree types can have multiple leaves containing a point;
          *          if non-NULL, this parameter is returned true if multiple leaves contain
          *          the input point
@@ -97,22 +101,30 @@ namespace moab {
          */
       ErrorCode point_search(const double *point,
                              AdaptiveKDTreeIter& leaf_it,
+                             double tol = 0.0,
                              bool *multiple_leaves = NULL,
                              EntityHandle *start_node = NULL);
       
         /** \brief Find all leaves within a given distance from point
          * If dists_out input non-NULL, also returns distances from each leaf; if
-         * point i is inside leaf, 0 is given as dists_out[i]
+         * point i is inside leaf, 0 is given as dists_out[i].
+         * If params_out is non-NULL and myEval is non-NULL, will evaluate individual entities
+         * in tree nodes and return containing entities in leaves_out.  In those cases, if params_out
+         * is also non-NULL, will return parameters in those elements in that vector.
          * \param point Point to be located in tree
          * \param distance Distance within which to query
-         * \param leaves Leaves within distance or containing point
-         * \param dists If non-NULL, will contain distsances to leaves
+         * \param leaves_out Leaves within distance or containing point
+         * \param tol Tolerance below which a point is "in"
+         * \param dists_out If non-NULL, will contain distsances to leaves
+         * \param params_out If non-NULL, will contain parameters of the point in the ents in leaves_out
          * \param start_node Start from this tree node (non-NULL) instead of tree root (NULL)
          */
       virtual ErrorCode distance_search(const double *point,
                                         const double distance,
                                         std::vector<EntityHandle>& leaves_out,
+                                        double tol = 0.0,
                                         std::vector<double> *dists_out = NULL,
+                                        std::vector<CartVect> *params_out = NULL,
                                         EntityHandle *start_node = NULL);
       
       ErrorCode get_info(EntityHandle root,

diff --git a/src/moab/BVHTree.hpp b/src/moab/BVHTree.hpp
index 2d472a0..f80462d 100644
--- a/src/moab/BVHTree.hpp
+++ b/src/moab/BVHTree.hpp
@@ -74,6 +74,7 @@ namespace moab {
          * containing the point in that case.
          * \param point Point to be located in tree
          * \param leaf_out Leaf containing point
+         * \param tol Tolerance below which a point is "in"
          * \param multiple_leaves Some tree types can have multiple leaves containing a point;
          *          if non-NULL, this parameter is returned true if multiple leaves contain
          *          the input point
@@ -82,26 +83,36 @@ namespace moab {
          */
       virtual ErrorCode point_search(const double *point,
                                      EntityHandle& leaf_out,
+                                     double tol = 0.0,
                                      bool *multiple_leaves = NULL,
-                                     EntityHandle *start_node = NULL);
+                                     EntityHandle *start_node = NULL,
+                                     CartVect *params = NULL);
 
         /** \brief Find all leaves within a given distance from point
          * If dists_out input non-NULL, also returns distances from each leaf; if
-         * point i is inside leaf, 0 is given as dists_out[i]
-         * \param from_point Point to be located in tree
+         * point i is inside leaf, 0 is given as dists_out[i].
+         * If params_out is non-NULL and myEval is non-NULL, will evaluate individual entities
+         * in tree nodes and return containing entities in leaves_out.  In those cases, if params_out
+         * is also non-NULL, will return parameters in those elements in that vector.
+         * \param point Point to be located in tree
          * \param distance Distance within which to query
-         * \param result_list Leaves within distance or containing point
-         * \param result_dists If non-NULL, will contain distsances to leaves
-         * \param tree_root Start from this tree node (non-NULL) instead of tree root (NULL)
+         * \param leaves_out Leaves within distance or containing point
+         * \param tol Tolerance below which a point is "in"
+         * \param dists_out If non-NULL, will contain distsances to leaves
+         * \param params_out If non-NULL, will contain parameters of the point in the ents in leaves_out
+         * \param start_node Start from this tree node (non-NULL) instead of tree root (NULL)
          */
       virtual ErrorCode distance_search(const double from_point[3],
                                         const double distance,
                                         std::vector<EntityHandle>& result_list,
-                                        std::vector<double> *result_dists,
-                                        EntityHandle *tree_root);
+                                        double tol = 0.0,
+                                        std::vector<double> *result_dists = NULL,
+                                        std::vector<CartVect> *result_params = NULL,
+                                        EntityHandle *tree_root = NULL);
 
         //! print various things about this tree
       virtual ErrorCode print();
+
       
   private:
         // don't allow copy constructor, too complicated
@@ -286,7 +297,8 @@ namespace moab {
       return std::ceil(center/length)-1;
     }
 
-    inline BVHTree::BVHTree(Interface *impl) : Tree(impl), splitsPerDir(3) {boxTagName = treeName;}
+    inline BVHTree::BVHTree(Interface *impl) : 
+            Tree(impl), myEval(NULL), splitsPerDir(3), startSetHandle(0) {boxTagName = treeName;}
 
     inline unsigned int BVHTree::set_interval(BoundBox &interval, 
                                               std::vector<Bucket>::const_iterator begin, 

diff --git a/src/moab/BoundBox.hpp b/src/moab/BoundBox.hpp
index 5b846bb..9400944 100644
--- a/src/moab/BoundBox.hpp
+++ b/src/moab/BoundBox.hpp
@@ -67,11 +67,11 @@ namespace moab {
     }
 
     inline bool BoundBox::contains_point(const double *point, const double tol) const {
-      if (point[0] > bMin[0]-tol && point[0] < bMax[0]+tol &&
-          point[1] > bMin[1]-tol && point[1] < bMax[1]+tol &&
-          point[2] > bMin[2]-tol && point[2] < bMax[2]+tol)
-        return true;
-      else return false;
+      if (point[0] < bMin[0]-tol || point[0] > bMax[0]+tol ||
+          point[1] < bMin[1]-tol || point[1] > bMax[1]+tol ||
+          point[2] < bMin[2]-tol || point[2] > bMax[2]+tol)
+        return false;
+      else return true;
     }
 
     inline bool BoundBox::contains_box(const BoundBox &b, const double tol) const {

diff --git a/src/moab/Tree.hpp b/src/moab/Tree.hpp
index 2ff1f63..da2099a 100644
--- a/src/moab/Tree.hpp
+++ b/src/moab/Tree.hpp
@@ -21,6 +21,7 @@ namespace moab {
 
     class Interface;
     class Range;
+    class ElemEvaluator;
 
     class Tree
     {
@@ -99,6 +100,7 @@ namespace moab {
          * containing the point in that case.
          * \param point Point to be located in tree
          * \param leaf_out Leaf containing point
+         * \param tol Tolerance below which a point is "in"
          * \param multiple_leaves Some tree types can have multiple leaves containing a point;
          *          if non-NULL, this parameter is returned true if multiple leaves contain
          *          the input point
@@ -107,22 +109,31 @@ namespace moab {
          */
       virtual ErrorCode point_search(const double *point,
                                      EntityHandle& leaf_out,
+                                     double tol = 0.0,
                                      bool *multiple_leaves = NULL,
-                                     EntityHandle *start_node = NULL) = 0;
+                                     EntityHandle *start_node = NULL,
+                                     CartVect *params = NULL) = 0;
 
         /** \brief Find all leaves within a given distance from point
          * If dists_out input non-NULL, also returns distances from each leaf; if
-         * point i is inside leaf, 0 is given as dists_out[i]
+         * point i is inside leaf, 0 is given as dists_out[i].
+         * If params_out is non-NULL and myEval is non-NULL, will evaluate individual entities
+         * in tree nodes and return containing entities in leaves_out.  In those cases, if params_out
+         * is also non-NULL, will return parameters in those elements in that vector.
          * \param point Point to be located in tree
          * \param distance Distance within which to query
-         * \param leaves Leaves within distance or containing point
-         * \param dists If non-NULL, will contain distsances to leaves
+         * \param leaves_out Leaves within distance or containing point
+         * \param tol Tolerance below which a point is "in"
+         * \param dists_out If non-NULL, will contain distsances to leaves
+         * \param params_out If non-NULL, will contain parameters of the point in the ents in leaves_out
          * \param start_node Start from this tree node (non-NULL) instead of tree root (NULL)
          */
       virtual ErrorCode distance_search(const double *point,
                                         const double distance,
                                         std::vector<EntityHandle>& leaves_out,
+                                        double params_tol = 0.0,
                                         std::vector<double> *dists_out = NULL,
+                                        std::vector<CartVect> *params_out = NULL,
                                         EntityHandle *start_node = NULL) = 0;
 
         /** \brief Return the MOAB interface associated with this tree
@@ -153,6 +164,13 @@ namespace moab {
         //! print various things about this tree
       virtual ErrorCode print() = 0;
       
+        //! get/set the ElemEvaluator
+      inline ElemEvaluator *get_eval() {return myEval;}
+      
+        //! get/set the ElemEvaluator
+      inline void set_eval(ElemEvaluator *eval) {myEval = eval;}
+      
+            
   protected:
 
         /** \brief Parse options common to all trees
@@ -203,7 +221,9 @@ namespace moab {
 
         // tree traversal stats
       TreeStats treeStats;
-      
+
+        // element evaluator
+      ElemEvaluator *myEval;
     };
 
     inline Tree::Tree(Interface* iface) 

diff --git a/test/kd_tree_test.cpp b/test/kd_tree_test.cpp
index f8d637f..8f479d0 100644
--- a/test/kd_tree_test.cpp
+++ b/test/kd_tree_test.cpp
@@ -255,7 +255,7 @@ void test_tree_delete()
   Core mb;
   AdaptiveKDTree tool(&mb);
   Tag data;
-  const EntityHandle root = create_tree( tool, DEPTH, INTERVALS, &data );
+  create_tree( tool, DEPTH, INTERVALS, &data );
   
   err = tool.reset_tree();
   CHECK_ERR(err);
@@ -377,9 +377,9 @@ void test_point_search()
   }
   
     // compare leaf search to iterator search
-  rval = tool.point_search(right.array(), leaf, NULL, const_cast<EntityHandle*>(&root));
+  rval = tool.point_search(right.array(), leaf, 0.0, NULL, const_cast<EntityHandle*>(&root));
   CHECK_ERR(rval);
-  rval = tool.point_search(right.array(), iter, NULL, const_cast<EntityHandle*>(&root));
+  rval = tool.point_search(right.array(), iter, 0.0, NULL, const_cast<EntityHandle*>(&root));
   CHECK_ERR(rval);
   assert( iter.handle() == leaf );
   

diff --git a/test/kd_tree_time.cpp b/test/kd_tree_time.cpp
index e1fd3fa..7917295 100644
--- a/test/kd_tree_time.cpp
+++ b/test/kd_tree_time.cpp
@@ -128,7 +128,7 @@ int main( int argc, char* argv[] )
     if (query_triangles)
       rval = tool.closest_triangle( root, coords, pt, leaf );
     else
-      rval = tool.point_search(coords, leaf, NULL, &root);
+      rval = tool.point_search(coords, leaf, 0.0, NULL, &root);
     if (MB_SUCCESS != rval) {
       fprintf(stderr, "Failure (ErrorCode == %d) for point %d (%f, %f, %f)\n",
         (int)rval, (int)(count % length), coords[0], coords[1], coords[2] );

diff --git a/tools/mbcoupler/Coupler.cpp b/tools/mbcoupler/Coupler.cpp
index 9e567fa..9d7e3d4 100644
--- a/tools/mbcoupler/Coupler.cpp
+++ b/tools/mbcoupler/Coupler.cpp
@@ -618,7 +618,7 @@ ErrorCode Coupler::nat_param(double xyz[3],
   if (epsilon) {
     std::vector<double> dists;
     std::vector<EntityHandle> leaves;
-    result = myTree->distance_search(xyz, epsilon, leaves, &dists, &localRoot);
+    result = myTree->distance_search(xyz, epsilon, leaves, 0.0, &dists, NULL, &localRoot);
     if (leaves.empty()) 
       // not found returns success here, with empty list, just like case with no epsilon
       return MB_SUCCESS;
@@ -635,7 +635,7 @@ ErrorCode Coupler::nat_param(double xyz[3],
     }
   }
   else {
-    result = myTree->point_search(xyz, treeiter, NULL, &localRoot);
+    result = myTree->point_search(xyz, treeiter, 0.0, NULL, &localRoot);
     if(MB_ENTITY_NOT_FOUND==result) //point is outside of myTree's bounding box
       return MB_SUCCESS; 
     else if (MB_SUCCESS != result) {

diff --git a/tools/skin.cpp b/tools/skin.cpp
index 1e636c2..1764f87 100644
--- a/tools/skin.cpp
+++ b/tools/skin.cpp
@@ -525,7 +525,7 @@ ErrorCode merge_duplicate_vertices( Interface& moab, const double epsilon )
     if (MB_SUCCESS != rval) return rval;
     
     leaves.clear();;
-    rval = tree.distance_search(coords, epsilon, leaves, NULL, &root);
+    rval = tree.distance_search(coords, epsilon, leaves, epsilon);
     if (MB_SUCCESS != rval) return rval;
     
     Range near;


https://bitbucket.org/fathomteam/moab/commits/3eb666a85667/
Changeset:   3eb666a85667
Branch:      None
User:        tautges
Date:        2013-06-05 17:59:55
Summary:     Merged fathomteam/moab into master
Affected #:  5 files

diff --git a/MeshFiles/unittest/io/fv26x46x72.t.3.nc b/MeshFiles/unittest/io/fv26x46x72.t.3.nc
new file mode 100644
index 0000000..15ba5b4
Binary files /dev/null and b/MeshFiles/unittest/io/fv26x46x72.t.3.nc differ

diff --git a/config/compiler.m4 b/config/compiler.m4
index 81596a6..6a7e2ed 100644
--- a/config/compiler.m4
+++ b/config/compiler.m4
@@ -102,15 +102,27 @@ if test "xno" != "x$WITH_MPI"; then
   DISTCHECK_CONFIGURE_FLAGS="$DISTCHECK_CONFIGURE_FLAGS --with-mpi=\"${withval}\""
   
   if test "xyes" == "x$WITH_MPI"; then
+    if test "xno" != "x$CHECK_CC"; then  
     FATHOM_SET_MPI_COMPILER([CC],  [$CC_LIST])
+    fi
+    if test "xno" != "x$CHECK_CXX"; then  
     FATHOM_SET_MPI_COMPILER([CXX],[$CXX_LIST])
-    FATHOM_SET_MPI_COMPILER([FC],  [$FC_LIST])
-    FATHOM_SET_MPI_COMPILER([F77],[$F77_LIST])
+    fi
+    if test "xno" != "x$CHECK_FC"; then  
+      FATHOM_SET_MPI_COMPILER([FC],  [$FC_LIST])
+      FATHOM_SET_MPI_COMPILER([F77],[$F77_LIST])
+    fi
   else
+    if test "xno" != "x$CHECK_CC"; then  
     FATHOM_SET_MPI_COMPILER([CC],  [$CC_LIST],[${WITH_MPI}/bin])
+    fi
+    if test "xno" != "x$CHECK_CXX"; then  
     FATHOM_SET_MPI_COMPILER([CXX],[$CXX_LIST],[${WITH_MPI}/bin])
-    FATHOM_SET_MPI_COMPILER([FC],  [$FC_LIST],[${WITH_MPI}/bin])
-    FATHOM_SET_MPI_COMPILER([F77],[$F77_LIST],[${WITH_MPI}/bin])
+    fi
+    if test "xno" != "x$CHECK_FC"; then
+      FATHOM_SET_MPI_COMPILER([FC],  [$FC_LIST],[${WITH_MPI}/bin])
+      FATHOM_SET_MPI_COMPILER([F77],[$F77_LIST],[${WITH_MPI}/bin])
+    fi
     WITH_MPI=yes
   fi
 fi

diff --git a/configure.ac b/configure.ac
index 2e9646f..21d5fa6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -41,6 +41,7 @@ else
   AM_SILENT_RULES(no)
 fi
 ])
+AC_C_BIGENDIAN
 
 # Check if platform is BlueGene
 AC_MSG_CHECKING([if platform is IBM BlueGene])

This diff is so big that we needed to truncate the remainder.

https://bitbucket.org/fathomteam/moab/commits/5ed8ba36aafb/
Changeset:   5ed8ba36aafb
Branch:      None
User:        tautges
Date:        2013-06-07 16:37:49
Summary:     Merged fathomteam/moab into master
Affected #:  15 files

diff --git a/MeshFiles/unittest/io/Makefile.am b/MeshFiles/unittest/io/Makefile.am
index ece20cf..8257e5f 100644
--- a/MeshFiles/unittest/io/Makefile.am
+++ b/MeshFiles/unittest/io/Makefile.am
@@ -3,6 +3,7 @@ EXTRA_DIST = HommeMapping.nc \
              brick_cubit10.2.cub \
              brick_cubit10.cub \
              camEul26x48x96.t3.nc \
+             fv26x46x72.t.3.nc \
 	     cubtest12.cub \
 	     cubtest.jou \
 	     dum.sat \

diff --git a/src/io/Makefile.am b/src/io/Makefile.am
index 9c76524..b7eae6a 100644
--- a/src/io/Makefile.am
+++ b/src/io/Makefile.am
@@ -16,8 +16,12 @@ if NETCDF_FILE
   MOAB_NETCDF_SRCS = ReadNCDF.cpp  ReadNCDF.hpp \
                      WriteNCDF.cpp WriteNCDF.hpp \
                      WriteSLAC.cpp WriteSLAC.hpp \
-		     ReadNC.cpp ReadNC.hpp \
-	  	     ReadGCRM.cpp ReadGCRM.hpp
+                     ReadNC.cpp ReadNC.hpp \
+                     NCHelper.cpp NCHelper.hpp \
+                     NCHelperEuler.cpp NCHelperEuler.hpp \
+                     NCHelperFV.cpp NCHelperFV.hpp \
+                     NCHelperHOMME.cpp NCHelperHOMME.hpp \
+                     ReadGCRM.cpp ReadGCRM.hpp
 else
   MOAB_NETCDF_SRCS =
 endif
@@ -25,7 +29,11 @@ endif
 if PNETCDF_FILE
 if !NETCDF_FILE
      MOAB_NETCDF_SRCS += ReadNC.cpp ReadNC.hpp \
-	  	     ReadGCRM.cpp ReadGCRM.hpp
+                     NCHelper.cpp NCHelper.hpp \
+                     NCHelperEuler.cpp NCHelperEuler.hpp \
+                     NCHelperFV.cpp NCHelperFV.hpp \
+                     NCHelperHOMME.cpp NCHelperHOMME.hpp \
+                     ReadGCRM.cpp ReadGCRM.hpp
 endif
 endif
 

diff --git a/src/io/NCHelper.cpp b/src/io/NCHelper.cpp
new file mode 100644
index 0000000..e0f021e
--- /dev/null
+++ b/src/io/NCHelper.cpp
@@ -0,0 +1,21 @@
+#include "NCHelper.hpp"
+#include "NCHelperEuler.hpp"
+#include "NCHelperFV.hpp"
+#include "NCHelperHOMME.hpp"
+#include "moab/ReadUtilIface.hpp"
+
+namespace moab {
+
+NCHelper* NCHelper::get_nc_helper(ReadNC* readNC, int fileId, const FileOptions& opts)
+{
+  if (NCHelperEuler::can_read_file(readNC, fileId))
+    return new (std::nothrow) NCHelperEuler(readNC, fileId);
+  else if (NCHelperFV::can_read_file(readNC, fileId))
+    return new (std::nothrow) NCHelperFV(readNC, fileId);
+  else if (NCHelperHOMME::can_read_file(readNC, fileId))
+    return new (std::nothrow) NCHelperHOMME(readNC, fileId, opts);
+  else // Unknown NetCDF grid (will fill this in later for POP, CICE and CLM)
+    return NULL;
+}
+
+} // namespace moab

diff --git a/src/io/NCHelper.hpp b/src/io/NCHelper.hpp
new file mode 100644
index 0000000..852fc61
--- /dev/null
+++ b/src/io/NCHelper.hpp
@@ -0,0 +1,36 @@
+//-------------------------------------------------------------------------
+// Filename      : NCHelper.hpp
+//
+// Purpose       : Climate NC file helper
+//
+// Creator       : Danqing Wu
+//-------------------------------------------------------------------------
+
+#ifndef NCHELPER_HPP
+#define NCHELPER_HPP
+
+#include "ReadNC.hpp"
+
+namespace moab {
+
+//! Helper class to isolate reading of several different nc file formats
+class NCHelper
+{
+public:
+  NCHelper(ReadNC* readNC, int fileId) : _readNC(readNC), _fileId(fileId) {}
+
+  static NCHelper* get_nc_helper(ReadNC* readNC, int fileId, const FileOptions& opts);
+
+  virtual ErrorCode init_mesh_vals(const FileOptions& opts, EntityHandle file_set) = 0;
+  virtual ErrorCode create_verts_quads(ScdInterface* scdi, const FileOptions& opts, EntityHandle file_set, Range& quads) = 0;
+  virtual std::string get_mesh_type_name() = 0;
+  virtual bool is_scd_mesh() = 0;
+
+protected:
+  ReadNC* _readNC;
+  int _fileId;
+};
+
+} // namespace moab
+
+#endif

diff --git a/src/io/NCHelperEuler.cpp b/src/io/NCHelperEuler.cpp
new file mode 100644
index 0000000..a01d4b8
--- /dev/null
+++ b/src/io/NCHelperEuler.cpp
@@ -0,0 +1,481 @@
+#include "NCHelperEuler.hpp"
+#include "moab/ReadUtilIface.hpp"
+#include "FileOptions.hpp"
+
+#include <cmath>
+#include <sstream>
+
+#define ERRORR(rval, str) \
+    if (MB_SUCCESS != rval) {_readNC->readMeshIface->report_error("%s", str); return rval;}
+
+#define ERRORS(err, str) \
+    if (err) {_readNC->readMeshIface->report_error("%s", str); return MB_FAILURE;}
+
+namespace moab {
+
+bool NCHelperEuler::can_read_file(ReadNC* readNC, int fileId)
+{
+  std::vector<std::string>& dimNames = readNC->dimNames;
+
+  // If dimension names "lon" AND "lat' exist then it could be either the Eulerian Spectral grid or the FV grid
+  if ((std::find(dimNames.begin(), dimNames.end(), std::string("lon")) != dimNames.end()) && (std::find(dimNames.begin(),
+      dimNames.end(), std::string("lat")) != dimNames.end())) {
+    // If dimension names "lon" AND "lat" AND "slon" AND "slat" exist then it should be the FV grid
+    if ((std::find(dimNames.begin(), dimNames.end(), std::string("slon")) != dimNames.end()) && (std::find(dimNames.begin(),
+        dimNames.end(), std::string("slat")) != dimNames.end()))
+      return false;
+
+    // Make sure it is CAM grid
+    std::map<std::string, ReadNC::AttData>::iterator attIt = readNC->globalAtts.find("source");
+    if (attIt == readNC->globalAtts.end()) {
+      readNC->readMeshIface->report_error("%s", "File does not have source global attribute.");
+      return false;
+    }
+    unsigned int sz = attIt->second.attLen;
+    std::string att_data;
+    att_data.resize(sz + 1);
+    att_data[sz] = '\000';
+    int success = NCFUNC(get_att_text)(fileId, attIt->second.attVarId, attIt->second.attName.c_str(), &att_data[0]);
+    if (success != 0) {
+      readNC->readMeshIface->report_error("%s", "Failed to read source global attribute char data.");
+      return false;
+    }
+    if (att_data.find("CAM") == std::string::npos)
+      return false;
+
+    return true;
+  }
+
+  return false;
+}
+
+ErrorCode NCHelperEuler::init_mesh_vals(const FileOptions& opts, EntityHandle file_set)
+{
+  Interface*& mbImpl = _readNC->mbImpl;
+  std::vector<std::string>& dimNames = _readNC->dimNames;
+  std::vector<int>& dimVals = _readNC->dimVals;
+  std::string& iName = _readNC->iName;
+  std::string& jName = _readNC->jName;
+  std::string& tName = _readNC->tName;
+  std::string& iCName = _readNC->iCName;
+  std::string& jCName = _readNC->jCName;
+  std::map<std::string, ReadNC::VarData>& varInfo = _readNC->varInfo;
+  int& tMin = _readNC->tMin;
+  int& tMax = _readNC->tMax;
+  int (&gDims)[6] = _readNC->gDims;
+  int (&lDims)[6] = _readNC->lDims;
+  int (&lCDims)[6] = _readNC->lCDims;
+  int (&gCDims)[6] = _readNC->gCDims;
+  std::vector<double>& ilVals = _readNC->ilVals;
+  std::vector<double>& jlVals = _readNC->jlVals;
+  std::vector<double>& tVals = _readNC->tVals;
+  std::vector<double>& ilCVals = _readNC->ilCVals;
+  std::vector<double>& jlCVals = _readNC->jlCVals;
+  int& tDim = _readNC->tDim;
+  int& iCDim = _readNC->iCDim;
+  int& jCDim = _readNC->jCDim;
+  DebugOutput& dbgOut = _readNC->dbgOut;
+  bool& isParallel = _readNC->isParallel;
+  int& partMethod = _readNC->partMethod;
+  int (&locallyPeriodic)[2] = _readNC->locallyPeriodic;
+  int (&globallyPeriodic)[2] = _readNC->globallyPeriodic;
+  ScdParData& parData = _readNC->parData;
+#ifdef USE_MPI
+  ParallelComm*& myPcomm = _readNC->myPcomm;
+#endif
+
+  // look for names of center i/j dimensions
+  std::vector<std::string>::iterator vit;
+  unsigned int idx;
+  iCName = std::string("lon");
+  iName = std::string("slon");
+  if ((vit = std::find(dimNames.begin(), dimNames.end(), iCName.c_str())) != dimNames.end())
+    idx = vit - dimNames.begin();
+  else {
+    ERRORR(MB_FAILURE, "Couldn't find center i variable.");
+  }
+  iCDim = idx;
+
+  // decide on i periodicity using math for now
+  std::vector<double> tilVals(dimVals[idx]);
+  ErrorCode rval = _readNC->read_coordinate(iCName.c_str(), 0, dimVals[idx] - 1, tilVals);
+  ERRORR(rval, "Trouble reading lon variable.");
+  if (std::fabs(2 * (*(tilVals.rbegin())) - *(tilVals.rbegin() + 1) - 360) < 0.001)
+    globallyPeriodic[0] = 1;
+
+  // now we can set gCDims and gDims for i
+  gCDims[0] = 0;
+  gDims[0] = 0;
+  gCDims[3] = dimVals[idx] - 1; // these are stored directly in file
+  gDims[3] = gCDims[3] + (globallyPeriodic[0] ? 0 : 1); // only if not periodic is vertex param max > elem param max
+
+  // now j
+  jCName = std::string("lat");
+  jName = std::string("slat");
+  if ((vit = std::find(dimNames.begin(), dimNames.end(), jCName.c_str())) != dimNames.end())
+    idx = vit - dimNames.begin();
+  else {
+    ERRORR(MB_FAILURE, "Couldn't find center j variable.");
+  }
+  jCDim = idx;
+
+  // for Eul models, will always be non-periodic in j
+  gCDims[1] = 0;
+  gDims[1] = 0;
+  gCDims[4] = dimVals[idx] - 1;
+  gDims[4] = gCDims[4] + 1;
+
+  // try a truly 2d mesh
+  gDims[2] = -1;
+  gDims[5] = -1;
+
+  // look for time dimensions
+  if ((vit = std::find(dimNames.begin(), dimNames.end(), "time")) != dimNames.end())
+    idx = vit - dimNames.begin();
+  else if ((vit = std::find(dimNames.begin(), dimNames.end(), "t")) != dimNames.end())
+    idx = vit - dimNames.begin();
+  else {
+    ERRORR(MB_FAILURE, "Couldn't find time variable.");
+  }
+  tDim = idx;
+  tMax = dimVals[idx] - 1;
+  tMin = 0;
+  tName = dimNames[idx];
+
+  // parse options to get subset
+  if (isParallel) {
+#ifdef USE_MPI
+    for (int i = 0; i < 6; i++)
+      parData.gDims[i] = gDims[i];
+    for (int i = 0; i < 3; i++)
+      parData.gPeriodic[i] = globallyPeriodic[i];
+    parData.partMethod = partMethod;
+    int pdims[3];
+
+    rval = ScdInterface::compute_partition(myPcomm->proc_config().proc_size(),
+        myPcomm->proc_config().proc_rank(),
+        parData, lDims, locallyPeriodic, pdims);
+    if (MB_SUCCESS != rval)
+      return rval;
+    for (int i = 0; i < 3; i++)
+      parData.pDims[i] = pdims[i];
+
+    dbgOut.tprintf(1, "Partition: %dx%d (out of %dx%d)\n",
+        lDims[3] - lDims[0] + 1, lDims[4] - lDims[1] + 1,
+        gDims[3] - gDims[0] + 1, gDims[4] - gDims[1] + 1);
+    if (myPcomm->proc_config().proc_rank() == 0)
+      dbgOut.tprintf(1, "Contiguous chunks of size %d bytes.\n", 8 * (lDims[3] - lDims[0] + 1) * (lDims[4] - lDims[1] + 1));
+#endif
+  }
+  else {
+    for (int i = 0; i < 6; i++)
+      lDims[i] = gDims[i];
+    locallyPeriodic[0] = globallyPeriodic[0];
+  }
+
+  opts.get_int_option("IMIN", lDims[0]);
+  opts.get_int_option("IMAX", lDims[3]);
+  opts.get_int_option("JMIN", lDims[1]);
+  opts.get_int_option("JMAX", lDims[4]);
+
+  // now get actual coordinate values for vertices and cell centers; first resize
+  if (locallyPeriodic[0]) {
+    // if locally periodic, doesn't matter what global periodicity is, # vertex coords = # elem coords
+    ilVals.resize(lDims[3] - lDims[0] + 1);
+    ilCVals.resize(lDims[3] - lDims[0] + 1);
+    lCDims[3] = lDims[3];
+  }
+  else {
+    if (!locallyPeriodic[0] && globallyPeriodic[0] && lDims[3] > gDims[3]) {
+      // globally periodic and I'm the last proc, get fewer vertex coords than vertices in i
+      ilVals.resize(lDims[3] - lDims[0] + 1);
+      ilCVals.resize(lDims[3] - lDims[0]);
+      lCDims[3] = lDims[3] - 1;
+    }
+    else {
+      ilVals.resize(lDims[3] - lDims[0] + 1);
+      ilCVals.resize(lDims[3] - lDims[0]);
+      lCDims[3] = lDims[3] - 1;
+    }
+  }
+
+  lCDims[0] = lDims[0];
+  lCDims[4] = lDims[4] - 1;
+  lCDims[1] = lDims[1];
+
+  if (-1 != lDims[1]) {
+    jlVals.resize(lDims[4] - lDims[1] + 1);
+    jlCVals.resize(lCDims[4] - lCDims[1] + 1);
+  }
+
+  if (-1 != tMin)
+    tVals.resize(tMax - tMin + 1);
+
+  // now read coord values
+  std::map<std::string, ReadNC::VarData>::iterator vmit;
+  if (!ilCVals.empty()) {
+    if ((vmit = varInfo.find(iCName)) != varInfo.end() && (*vmit).second.varDims.size() == 1) {
+      rval = _readNC->read_coordinate(iCName.c_str(), lDims[0], lDims[0] + ilCVals.size() - 1, ilCVals);
+      ERRORR(rval, "Trouble reading lon variable.");
+    }
+    else {
+      ERRORR(MB_FAILURE, "Couldn't find lon coordinate.");
+    }
+  }
+
+  if (!jlCVals.empty()) {
+    if ((vmit = varInfo.find(jCName)) != varInfo.end() && (*vmit).second.varDims.size() == 1) {
+      rval = _readNC->read_coordinate(jCName.c_str(), lDims[1], lDims[1] + jlCVals.size() - 1, jlCVals);
+      ERRORR(rval, "Trouble reading lat variable.");
+    }
+    else {
+      ERRORR(MB_FAILURE, "Couldn't find lat coordinate.");
+    }
+  }
+
+  if (lDims[0] != -1) {
+    if ((vmit = varInfo.find(iCName)) != varInfo.end() && (*vmit).second.varDims.size() == 1) {
+      double dif = (ilCVals[1] - ilCVals[0]) / 2;
+      std::size_t i;
+      for (i = 0; i != ilCVals.size(); i++)
+        ilVals[i] = ilCVals[i] - dif;
+      // the last one is needed only if not periodic
+      if (!locallyPeriodic[0])
+        ilVals[i] = ilCVals[i - 1] + dif;
+    }
+    else {
+      ERRORR(MB_FAILURE, "Couldn't find x coordinate.");
+    }
+  }
+
+  if (lDims[1] != -1) {
+    if ((vmit = varInfo.find(jCName)) != varInfo.end() && (*vmit).second.varDims.size() == 1) {
+      if (!isParallel || ((gDims[4] - gDims[1]) == (lDims[4] - lDims[1]))) {
+        std::string gwName("gw");
+        std::vector<double> gwVals(lDims[4] - lDims[1] - 1);
+        rval = _readNC->read_coordinate(gwName.c_str(), lDims[1], lDims[4] - 2, gwVals);
+        ERRORR(rval, "Trouble reading gw variable.");
+        // copy the correct piece
+        jlVals[0] = -(M_PI / 2) * 180 / M_PI;
+        unsigned int i = 0;
+        double gwSum = -1;
+        for (i = 1; i != gwVals.size() + 1; i++) {
+          gwSum = gwSum + gwVals[i - 1];
+          jlVals[i] = std::asin(gwSum) * 180 / M_PI;
+        }
+        jlVals[i] = 90.0; // using value of i after loop exits.
+      }
+      else {
+        std::string gwName("gw");
+        double gwSum = 0;
+
+        // If this is the first row
+        if (lDims[1] == gDims[1]) {
+          std::vector<double> gwVals(lDims[4]);
+          rval = _readNC->read_coordinate(gwName.c_str(), 0, lDims[4] - 1, gwVals);
+          ERRORR(rval, "Trouble reading gw variable.");
+          // copy the correct piece
+          jlVals[0] = -(M_PI / 2) * 180 / M_PI;
+          gwSum = -1;
+          for (std::size_t i = 1; i != jlVals.size(); i++) {
+            gwSum = gwSum + gwVals[i - 1];
+            jlVals[i] = std::asin(gwSum) * 180 / M_PI;
+          }
+        }
+        // or if it's the last row
+        else if (lDims[4] == gDims[4]) {
+          std::vector<double> gwVals(lDims[4] - 1);
+          rval = _readNC->read_coordinate(gwName.c_str(), 0, lDims[4] - 2, gwVals);
+          ERRORR(rval, "Trouble reading gw variable.");
+          // copy the correct piece
+          gwSum = -1;
+          for (int j = 0; j != lDims[1] - 1; j++) {
+            gwSum = gwSum + gwVals[j];
+          }
+          std::size_t i = 0;
+          for (; i != jlVals.size() - 1; i++) {
+            gwSum = gwSum + gwVals[lDims[1] - 1 + i];
+            jlVals[i] = std::asin(gwSum) * 180 / M_PI;
+          }
+          jlVals[i] = 90.0; // using value of i after loop exits.
+        }
+        // it's in the middle
+        else {
+          int start = lDims[1] - 1;
+          int end = lDims[4] - 1;
+          std::vector<double> gwVals(end);
+          rval = _readNC->read_coordinate(gwName.c_str(), 0, end - 1, gwVals);
+          ERRORR(rval, "Trouble reading gw variable.");
+          gwSum = -1;
+          for (int j = 0; j != start - 1; j++) {
+            gwSum = gwSum + gwVals[j];
+          }
+          std::size_t i = 0;
+          for (; i != jlVals.size(); i++) {
+            gwSum = gwSum + gwVals[start - 1 + i];
+            jlVals[i] = std::asin(gwSum) * 180 / M_PI;
+          }
+        }
+      }
+    }
+    else {
+      ERRORR(MB_FAILURE, "Couldn't find y coordinate.");
+    }
+  }
+
+  if (tMin != -1) {
+    if ((vmit = varInfo.find(tName)) != varInfo.end() && (*vmit).second.varDims.size() == 1) {
+      rval = _readNC->read_coordinate(tName.c_str(), tMin, tMax, tVals);
+      ERRORR(rval, "Trouble reading time variable.");
+    }
+    else {
+      ERRORR(MB_FAILURE, "Couldn't find time coordinate.");
+    }
+  }
+
+  dbgOut.tprintf(1, "I=%d-%d, J=%d-%d\n", lDims[0], lDims[3], lDims[1], lDims[4]);
+  dbgOut.tprintf(1, "%d elements, %d vertices\n", (lDims[3] - lDims[0]) * (lDims[4] - lDims[1]), (lDims[3] - lDims[0] + 1)
+      * (lDims[4] - lDims[1] + 1));
+
+  // determine the entity location type of a variable
+  std::map<std::string, ReadNC::VarData>::iterator mit;
+  for (mit = varInfo.begin(); mit != varInfo.end(); ++mit) {
+    ReadNC::VarData& vd = (*mit).second;
+    if ((std::find(vd.varDims.begin(), vd.varDims.end(), iCDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(),
+        vd.varDims.end(), jCDim) != vd.varDims.end()))
+      vd.entLoc = ReadNC::ENTLOCQUAD;
+  }
+
+  // <coordinate_dim_name>
+  std::vector<std::string> ijdimNames(4);
+  ijdimNames[0] = "__slon";
+  ijdimNames[1] = "__slat";
+  ijdimNames[2] = "__lon";
+  ijdimNames[3] = "__lat";
+
+  std::string tag_name;
+  int val_len = 0;
+  for (unsigned int i = 0; i != ijdimNames.size(); i++) {
+    tag_name = ijdimNames[i];
+    void * val = NULL;
+    if (tag_name == "__slon") {
+      val = &ilVals[0];
+      val_len = ilVals.size();
+    }
+    else if (tag_name == "__slat") {
+      val = &jlVals[0];
+      val_len = jlVals.size();
+    }
+    else if (tag_name == "__lon") {
+      val = &ilCVals[0];
+      val_len = ilCVals.size();
+    }
+    else if (tag_name == "__lat") {
+      val = &jlCVals[0];
+      val_len = jlCVals.size();
+    }
+    Tag tagh = 0;
+    DataType data_type;
+
+    // assume all has same data type as lon
+    switch (varInfo["lon"].varDataType) {
+      case NC_BYTE:
+      case NC_CHAR:
+      case NC_DOUBLE:
+        data_type = MB_TYPE_DOUBLE;
+        break;
+      case NC_FLOAT:
+        data_type = MB_TYPE_DOUBLE;
+        break;
+      case NC_INT:
+        data_type = MB_TYPE_INTEGER;
+        break;
+      case NC_SHORT:
+      default:
+        std::cerr << "Unrecognized data type for tag " << tag_name << std::endl;
+        ERRORR(MB_FAILURE, "Unrecognized data type");
+        break;
+    }
+    rval = mbImpl->tag_get_handle(tag_name.c_str(), 0, data_type, tagh, MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN);
+    ERRORR(rval, "Trouble creating <coordinate_dim_name> tag.");
+    rval = mbImpl->tag_set_by_ptr(tagh, &file_set, 1, &val, &val_len);
+    ERRORR(rval, "Trouble setting data for <coordinate_dim_name> tag.");
+    if (MB_SUCCESS == rval)
+      dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
+  }
+
+  // __<coordinate_dim_name>_LOC_MINMAX
+  for (unsigned int i = 0; i != ijdimNames.size(); i++) {
+    std::stringstream ss_tag_name;
+    ss_tag_name << ijdimNames[i] << "_LOC_MINMAX";
+    tag_name = ss_tag_name.str();
+    Tag tagh = 0;
+    std::vector<int> val(2, 0);
+    if (ijdimNames[i] == "__slon") {
+      val[0] = lDims[0];
+      val[1] = lDims[3];
+    }
+    else if (ijdimNames[i] == "__slat") {
+      val[0] = lDims[1];
+      val[1] = lDims[4];
+    }
+    else if (ijdimNames[i] == "__lon") {
+      val[0] = lCDims[0];
+      val[1] = lCDims[3];
+    }
+    else if (ijdimNames[i] == "__lat") {
+      val[0] = lCDims[1];
+      val[1] = lCDims[4];
+    }
+    rval = mbImpl->tag_get_handle(tag_name.c_str(), 2, MB_TYPE_INTEGER, tagh, MB_TAG_SPARSE | MB_TAG_CREAT);
+    ERRORR(rval, "Trouble creating __<coordinate_dim_name>_LOC_MINMAX tag.");
+    rval = mbImpl->tag_set_data(tagh, &file_set, 1, &val[0]);
+    ERRORR(rval, "Trouble setting data for __<coordinate_dim_name>_LOC_MINMAX tag.");
+    if (MB_SUCCESS == rval)
+      dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
+  }
+
+  // __<coordinate_dim_name>_GLOBAL_MINMAX
+  for (unsigned int i = 0; i != ijdimNames.size(); i++) {
+    std::stringstream ss_tag_name;
+    ss_tag_name << ijdimNames[i] << "_GLOBAL_MINMAX";
+    tag_name = ss_tag_name.str();
+    Tag tagh = 0;
+    std::vector<int> val(2, 0);
+    if (ijdimNames[i] == "__slon") {
+      val[0] = gDims[0];
+      val[1] = gDims[3];
+    }
+    else if (ijdimNames[i] == "__slat") {
+      val[0] = gDims[1];
+      val[1] = gDims[4];
+    }
+    else if (ijdimNames[i] == "__lon") {
+      val[0] = gCDims[0];
+      val[1] = gCDims[3];
+    }
+    else if (ijdimNames[i] == "__lat") {
+      val[0] = gCDims[1];
+      val[1] = gCDims[4];
+    }
+    rval = mbImpl->tag_get_handle(tag_name.c_str(), 2, MB_TYPE_INTEGER, tagh, MB_TAG_SPARSE | MB_TAG_CREAT);
+    ERRORR(rval, "Trouble creating __<coordinate_dim_name>_GLOBAL_MINMAX tag.");
+    rval = mbImpl->tag_set_data(tagh, &file_set, 1, &val[0]);
+    ERRORR(rval, "Trouble setting data for __<coordinate_dim_name>_GLOBAL_MINMAX tag.");
+    if (MB_SUCCESS == rval)
+      dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
+  }
+
+  // hack: create dummy tags, if needed, for variables like nbnd
+  // with no corresponding variables
+  _readNC->init_dims_with_no_cvars_info();
+
+  return MB_SUCCESS;
+}
+
+ErrorCode NCHelperEuler::create_verts_quads(ScdInterface* scdi, const FileOptions& opts, EntityHandle file_set, Range& quads)
+{
+  return _readNC->create_scd_verts_quads(scdi, file_set, quads);
+}
+
+} // namespace moab

diff --git a/src/io/NCHelperEuler.hpp b/src/io/NCHelperEuler.hpp
new file mode 100644
index 0000000..b1c4c21
--- /dev/null
+++ b/src/io/NCHelperEuler.hpp
@@ -0,0 +1,36 @@
+//-------------------------------------------------------------------------
+// Filename      : NCHelperEuler.hpp
+//
+// Purpose       : Climate NC file helper for Eulerian Spectral grid
+//
+// Creator       : Danqing Wu
+//-------------------------------------------------------------------------
+
+#ifndef NCHELPEREULER_HPP
+#define NCHELPEREULER_HPP
+
+#include "NCHelper.hpp"
+
+namespace moab {
+
+//! Child helper class for Eulerian Spectral grid (CAM_EUL)
+class NCHelperEuler : public NCHelper
+{
+public:
+  NCHelperEuler(ReadNC* readNC, int fileId) : NCHelper(readNC, fileId) {}
+
+  static bool can_read_file(ReadNC* readNC, int fileId);
+
+private:
+  virtual ErrorCode init_mesh_vals(const FileOptions& opts, EntityHandle file_set);
+
+  virtual ErrorCode create_verts_quads(ScdInterface* scdi, const FileOptions& opts, EntityHandle file_set, Range& quads);
+
+  virtual std::string get_mesh_type_name() { return "CAM_EUL"; }
+
+  virtual bool is_scd_mesh() { return true; }
+};
+
+} // namespace moab
+
+#endif

diff --git a/src/io/NCHelperFV.cpp b/src/io/NCHelperFV.cpp
new file mode 100644
index 0000000..566b719
--- /dev/null
+++ b/src/io/NCHelperFV.cpp
@@ -0,0 +1,477 @@
+#include "NCHelperFV.hpp"
+#include "moab/ReadUtilIface.hpp"
+#include "FileOptions.hpp"
+
+#include <cmath>
+#include <sstream>
+
+#define ERRORR(rval, str) \
+    if (MB_SUCCESS != rval) {_readNC->readMeshIface->report_error("%s", str); return rval;}
+
+namespace moab {
+
+bool NCHelperFV::can_read_file(ReadNC* readNC, int fileId)
+{
+  std::vector<std::string>& dimNames = readNC->dimNames;
+
+  // If dimension names "lon" AND "lat" AND "slon" AND "slat" exist then it should be the FV grid
+  if ((std::find(dimNames.begin(), dimNames.end(), std::string("lon")) != dimNames.end()) && (std::find(dimNames.begin(),
+      dimNames.end(), std::string("lat")) != dimNames.end()) && (std::find(dimNames.begin(), dimNames.end(), std::string("slon"))
+      != dimNames.end()) && (std::find(dimNames.begin(), dimNames.end(), std::string("slat")) != dimNames.end())) {
+    // Make sure it is CAM grid
+    std::map<std::string, ReadNC::AttData>::iterator attIt = readNC->globalAtts.find("source");
+    if (attIt == readNC->globalAtts.end()) {
+      readNC->readMeshIface->report_error("%s", "File does not have source global attribute.");
+      return false;
+    }
+    unsigned int sz = attIt->second.attLen;
+    std::string att_data;
+    att_data.resize(sz + 1);
+    att_data[sz] = '\000';
+    int success = NCFUNC(get_att_text)(fileId, attIt->second.attVarId, attIt->second.attName.c_str(), &att_data[0]);
+    if (success != 0) {
+      readNC->readMeshIface->report_error("%s", "Failed to read source global attribute char data.");
+      return false;
+    }
+    if (att_data.find("CAM") == std::string::npos)
+      return false;
+
+    return true;
+  }
+
+  return false;
+}
+
+ErrorCode NCHelperFV::init_mesh_vals(const FileOptions& opts, EntityHandle file_set)
+{
+  Interface*& mbImpl = _readNC->mbImpl;
+  std::vector<std::string>& dimNames = _readNC->dimNames;
+  std::vector<int>& dimVals = _readNC->dimVals;
+  std::string& iName = _readNC->iName;
+  std::string& jName = _readNC->jName;
+  std::string& tName = _readNC->tName;
+  std::string& iCName = _readNC->iCName;
+  std::string& jCName = _readNC->jCName;
+  std::map<std::string, ReadNC::VarData>& varInfo = _readNC->varInfo;
+  int& tMin = _readNC->tMin;
+  int& tMax = _readNC->tMax;
+  int (&gDims)[6] = _readNC->gDims;
+  int (&lDims)[6] = _readNC->lDims;
+  int (&gCDims)[6] = _readNC->gCDims;
+  int (&lCDims)[6] = _readNC->lCDims;
+  std::vector<double>& ilVals = _readNC->ilVals;
+  std::vector<double>& jlVals = _readNC->jlVals;
+  std::vector<double>& tVals = _readNC->tVals;
+  std::vector<double>& ilCVals = _readNC->ilCVals;
+  std::vector<double>& jlCVals = _readNC->jlCVals;
+  int& iDim = _readNC->iDim;
+  int& jDim = _readNC->jDim;
+  int& tDim = _readNC->tDim;
+  int& iCDim = _readNC->iCDim;
+  int& jCDim = _readNC->jCDim;
+  DebugOutput& dbgOut = _readNC->dbgOut;
+  bool& isParallel = _readNC->isParallel;
+  int& partMethod = _readNC->partMethod;
+  int (&locallyPeriodic)[2] = _readNC->locallyPeriodic;
+  int (&globallyPeriodic)[2] = _readNC->globallyPeriodic;
+  ScdParData& parData = _readNC->parData;
+#ifdef USE_MPI
+  ParallelComm*& myPcomm = _readNC->myPcomm;
+#endif
+
+  std::vector<std::string>::iterator vit;
+  unsigned int idx;
+  if ((vit = std::find(dimNames.begin(), dimNames.end(), "slon")) != dimNames.end())
+    idx = vit - dimNames.begin();
+  else {
+    ERRORR(MB_FAILURE, "Couldn't find slon variable.");
+  }
+
+  iDim = idx;
+  gDims[3] = dimVals[idx] - 1;
+  gDims[0] = 0;
+  iName = dimNames[idx];
+
+  if ((vit = std::find(dimNames.begin(), dimNames.end(), "slat")) != dimNames.end())
+    idx = vit - dimNames.begin();
+  else {
+    ERRORR(MB_FAILURE, "Couldn't find slat variable.");
+  }
+  jDim = idx;
+  gDims[4] = dimVals[idx] - 1 + 2; // add 2 for the pole points
+  gDims[1] = 0;
+  jName = dimNames[idx];
+
+  // look for names of center i/j dimensions
+  if ((vit = std::find(dimNames.begin(), dimNames.end(), "lon")) != dimNames.end())
+    idx = vit - dimNames.begin();
+  else {
+    ERRORR(MB_FAILURE, "Couldn't find lon variable.");
+  }
+  iCDim = idx;
+  gCDims[3] = dimVals[idx] - 1;
+  gCDims[0] = 0;
+  iCName = dimNames[idx];
+
+  // check and set globallyPeriodic[0]
+  std::vector<double> til_vals(2);
+  ErrorCode rval = _readNC->read_coordinate(iCName.c_str(), dimVals[idx] - 2, dimVals[idx] - 1, til_vals);
+  ERRORR(rval, "Trouble reading slon variable.");
+  if (std::fabs(2 * til_vals[1] - til_vals[0] - 360) < 0.001)
+    globallyPeriodic[0] = 1;
+  if (globallyPeriodic[0])
+    assert("Number of vertices and edges should be same" && gDims[3] == gCDims[3]);
+  else
+    assert("Number of vertices should equal to number of edges plus one" && gDims[3] == gCDims[3] + 1);
+
+#ifdef USE_MPI
+  // if serial, use a locally-periodic representation only if local mesh is periodic, otherwise don't
+  if ((isParallel && myPcomm->proc_config().proc_size() == 1) && globallyPeriodic[0])
+    locallyPeriodic[0] = 1;
+#else
+  if (globallyPeriodic[0])
+    locallyPeriodic[0] = 1;
+#endif
+
+  if ((vit = std::find(dimNames.begin(), dimNames.end(), "lat")) != dimNames.end())
+    idx = vit - dimNames.begin();
+  else {
+    ERRORR(MB_FAILURE, "Couldn't find lat variable.");
+  }
+  jCDim = idx;
+  gCDims[4] = dimVals[idx] - 1;
+  gCDims[1] = 0;
+  jCName = dimNames[idx];
+
+  if ((vit = std::find(dimNames.begin(), dimNames.end(), "time")) != dimNames.end())
+    idx = vit - dimNames.begin();
+  else {
+    ERRORR(MB_FAILURE, "Couldn't find time variable.");
+  }
+  tDim = idx;
+  tMax = dimVals[idx] - 1;
+  tMin = 0;
+  tName = dimNames[idx];
+
+  // parse options to get subset
+  if (isParallel) {
+#ifdef USE_MPI
+    for (int i = 0; i < 6; i++)
+      parData.gDims[i] = gDims[i];
+    for (int i = 0; i < 3; i++)
+      parData.gPeriodic[i] = globallyPeriodic[i];
+    parData.partMethod = partMethod;
+    int pdims[3];
+
+    rval = ScdInterface::compute_partition(myPcomm->proc_config().proc_size(),
+        myPcomm->proc_config().proc_rank(),
+        parData, lDims, locallyPeriodic, pdims);
+    if (MB_SUCCESS != rval)
+      return rval;
+    for (int i = 0; i < 3; i++)
+      parData.pDims[i] = pdims[i];
+
+    dbgOut.tprintf(1, "Partition: %dx%d (out of %dx%d)\n",
+        lDims[3] - lDims[0] + 1, lDims[4] - lDims[1] + 1,
+        gDims[3] - gDims[0] + 1, gDims[4] - gDims[1] + 1);
+    if (myPcomm->proc_config().proc_rank() == 0)
+      dbgOut.tprintf(1, "Contiguous chunks of size %d bytes.\n", 8 * (lDims[3] - lDims[0] + 1) * (lDims[4] - lDims[1] + 1));
+#endif
+  }
+  else {
+    for (int i = 0; i < 6; i++)
+      lDims[i] = gDims[i];
+    locallyPeriodic[0] = globallyPeriodic[0];
+  }
+  opts.get_int_option("IMIN", lDims[0]);
+  opts.get_int_option("IMAX", lDims[3]);
+  opts.get_int_option("JMIN", lDims[1]);
+  opts.get_int_option("JMAX", lDims[4]);
+
+  // now get actual coordinate values for vertices and cell centers; first resize
+  if (locallyPeriodic[0]) {
+    // if locally periodic, doesn't matter what global periodicity is, # vertex coords = # elem coords
+    ilVals.resize(lDims[3] - lDims[0] + 1);
+    ilCVals.resize(lDims[3] - lDims[0] + 1);
+    lCDims[3] = lDims[3];
+  }
+  else {
+    if (!locallyPeriodic[0] && globallyPeriodic[0] && lDims[3] > gDims[3]) {
+      // globally periodic and I'm the last proc, get fewer vertex coords than vertices in i
+      ilVals.resize(lDims[3] - lDims[0] + 1);
+      ilCVals.resize(lDims[3] - lDims[0]);
+      lCDims[3] = lDims[3] - 1;
+    }
+    else {
+      ilVals.resize(lDims[3] - lDims[0] + 1);
+      ilCVals.resize(lDims[3] - lDims[0]);
+      lCDims[3] = lDims[3] - 1;
+    }
+  }
+
+  lCDims[0] = lDims[0];
+  lCDims[4] = lDims[4] - 1;
+  lCDims[1] = lDims[1];
+
+  if (-1 != lDims[1]) {
+    jlVals.resize(lDims[4] - lDims[1] + 1);
+    jlCVals.resize(lCDims[4] - lCDims[1] + 1);
+  }
+
+  if (-1 != tMin)
+    tVals.resize(tMax - tMin + 1);
+
+  // ... then read actual values
+  std::map<std::string, ReadNC::VarData>::iterator vmit;
+  if (lCDims[0] != -1) {
+    if ((vmit = varInfo.find(iCName)) != varInfo.end() && (*vmit).second.varDims.size() == 1) {
+      rval = _readNC->read_coordinate(iCName.c_str(), lCDims[0], lCDims[3], ilCVals);
+      ERRORR(rval, "Trouble reading lon variable.");
+    }
+    else {
+      ERRORR(MB_FAILURE, "Couldn't find lon coordinate.");
+    }
+  }
+
+  if (lCDims[1] != -1) {
+    if ((vmit = varInfo.find(jCName)) != varInfo.end() && (*vmit).second.varDims.size() == 1) {
+      rval = _readNC->read_coordinate(jCName.c_str(), lCDims[1], lCDims[4], jlCVals);
+      ERRORR(rval, "Trouble reading lat variable.");
+    }
+    else {
+      ERRORR(MB_FAILURE, "Couldn't find lat coordinate.");
+    }
+  }
+
+  if (lDims[0] != -1) {
+    if ((vmit = varInfo.find(iName)) != varInfo.end() && (*vmit).second.varDims.size() == 1) {
+      // last column
+      if (!locallyPeriodic[0] && globallyPeriodic[0] && lDims[3] > gDims[3]) {
+        til_vals.resize(ilVals.size() - 1, 0.0);
+        rval = _readNC->read_coordinate(iName.c_str(), lDims[0], lDims[3] - 1, til_vals);
+        double dif = til_vals[1] - til_vals[0];
+        std::size_t i;
+        for (i = 0; i != til_vals.size(); i++)
+          ilVals[i] = til_vals[i];
+        ilVals[i] = ilVals[i - 1] + dif;
+      }
+      else {
+        rval = _readNC->read_coordinate(iName.c_str(), lDims[0], lDims[3], ilVals);
+        ERRORR(rval, "Trouble reading x variable.");
+      }
+    }
+    else {
+      ERRORR(MB_FAILURE, "Couldn't find x coordinate.");
+    }
+  }
+
+  if (lDims[1] != -1) {
+    if ((vmit = varInfo.find(jName)) != varInfo.end() && (*vmit).second.varDims.size() == 1) {
+      if (!isParallel || ((gDims[4] - gDims[1]) == (lDims[4] - lDims[1]))) {
+        std::vector<double> dummyVar(lDims[4] - lDims[1] - 1);
+        rval = _readNC->read_coordinate(jName.c_str(), lDims[1], lDims[4] - 2, dummyVar);
+        ERRORR(rval, "Trouble reading y variable.");
+        // copy the correct piece
+        jlVals[0] = -90.0;
+        unsigned int i = 0;
+        for (i = 1; i != dummyVar.size() + 1; i++)
+          jlVals[i] = dummyVar[i - 1];
+        jlVals[i] = 90.0; // using value of i after loop exits.
+      }
+      else {
+        // If this is the first row
+        // need to read one less then available and read it into a dummy var
+        if (lDims[1] == gDims[1]) {
+          std::vector<double> dummyVar(lDims[4] - lDims[1]);
+          rval = _readNC->read_coordinate(jName.c_str(), lDims[1], lDims[4] - 1, dummyVar);
+          ERRORR(rval, "Trouble reading y variable.");
+          // copy the correct piece
+          jlVals[0] = -90.0;
+          for (int i = 1; i < lDims[4] + 1; i++)
+            jlVals[i] = dummyVar[i - 1];
+        }
+        // or if it's the last row
+        else if (lDims[4] == gDims[4]) {
+          std::vector<double> dummyVar(lDims[4] - lDims[1]);
+          rval = _readNC->read_coordinate(jName.c_str(), lDims[1] - 1, lDims[4] - 2, dummyVar);
+          ERRORR(rval, "Trouble reading y variable.");
+          // copy the correct piece
+          std::size_t i = 0;
+          for (i = 0; i != dummyVar.size(); i++)
+            jlVals[i] = dummyVar[i];
+          jlVals[i] = 90.0; // using value of i after loop exits.
+        }
+        // it's in the middle
+        else {
+          rval = _readNC->read_coordinate(jCName.c_str(), lDims[1] - 1, lDims[4] - 1, jlVals);
+          ERRORR(rval, "Trouble reading y variable.");
+        }
+      }
+    }
+    else {
+      ERRORR(MB_FAILURE, "Couldn't find y coordinate.");
+    }
+  }
+
+  if (tMin != -1) {
+    if ((vmit = varInfo.find(tName)) != varInfo.end() && (*vmit).second.varDims.size() == 1) {
+      rval = _readNC->read_coordinate(tName.c_str(), tMin, tMax, tVals);
+      ERRORR(rval, "Trouble reading time variable.");
+    }
+    else {
+      ERRORR(MB_FAILURE, "Couldn't find time coordinate.");
+    }
+  }
+
+  dbgOut.tprintf(1, "I=%d-%d, J=%d-%d\n", lDims[0], lDims[3], lDims[1], lDims[4]);
+  dbgOut.tprintf(1, "%d elements, %d vertices\n", (lDims[3] - lDims[0]) * (lDims[4] - lDims[1]), (lDims[3] - lDims[0] + 1)
+      * (lDims[4] - lDims[1] + 1));
+
+  // determine the entity location type of a variable
+  std::map<std::string, ReadNC::VarData>::iterator mit;
+  for (mit = varInfo.begin(); mit != varInfo.end(); ++mit) {
+    ReadNC::VarData& vd = (*mit).second;
+    if ((std::find(vd.varDims.begin(), vd.varDims.end(), iCDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(),
+        vd.varDims.end(), jCDim) != vd.varDims.end()))
+      vd.entLoc = ReadNC::ENTLOCQUAD;
+    else if ((std::find(vd.varDims.begin(), vd.varDims.end(), jDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(),
+        vd.varDims.end(), iCDim) != vd.varDims.end()))
+      vd.entLoc = ReadNC::ENTLOCNSEDGE;
+    else if ((std::find(vd.varDims.begin(), vd.varDims.end(), jCDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(),
+        vd.varDims.end(), iDim) != vd.varDims.end()))
+      vd.entLoc = ReadNC::ENTLOCEWEDGE;
+  }
+
+  // <coordinate_dim_name>
+  std::vector<std::string> ijdimNames(4);
+  ijdimNames[0] = "__slon";
+  ijdimNames[1] = "__slat";
+  ijdimNames[2] = "__lon";
+  ijdimNames[3] = "__lat";
+
+  std::string tag_name;
+  int val_len = 0;
+  for (unsigned int i = 0; i != ijdimNames.size(); i++) {
+    tag_name = ijdimNames[i];
+    void * val = NULL;
+    if (tag_name == "__slon") {
+      val = &ilVals[0];
+      val_len = ilVals.size();
+    }
+    else if (tag_name == "__slat") {
+      val = &jlVals[0];
+      val_len = jlVals.size();
+    }
+    else if (tag_name == "__lon") {
+      val = &ilCVals[0];
+      val_len = ilCVals.size();
+    }
+    else if (tag_name == "__lat") {
+      val = &jlCVals[0];
+      val_len = jlCVals.size();
+    }
+    Tag tagh = 0;
+    DataType data_type;
+
+    // assume all has same data type as lon
+    switch (varInfo["lon"].varDataType) {
+      case NC_BYTE:
+      case NC_CHAR:
+      case NC_DOUBLE:
+        data_type = MB_TYPE_DOUBLE;
+        break;
+      case NC_FLOAT:
+        data_type = MB_TYPE_DOUBLE;
+        break;
+      case NC_INT:
+        data_type = MB_TYPE_INTEGER;
+        break;
+      case NC_SHORT:
+      default:
+        std::cerr << "Unrecognized data type for tag " << tag_name << std::endl;
+        ERRORR(MB_FAILURE, "Unrecognized data type");
+        break;
+    }
+    rval = mbImpl->tag_get_handle(tag_name.c_str(), 0, data_type, tagh, MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN);
+    ERRORR(rval, "Trouble creating <coordinate_dim_name> tag.");
+    rval = mbImpl->tag_set_by_ptr(tagh, &file_set, 1, &val, &val_len);
+    ERRORR(rval, "Trouble setting data for <coordinate_dim_name> tag.");
+    if (MB_SUCCESS == rval)
+      dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
+  }
+
+  // __<coordinate_dim_name>_LOC_MINMAX
+  for (unsigned int i = 0; i != ijdimNames.size(); i++) {
+    std::stringstream ss_tag_name;
+    ss_tag_name << ijdimNames[i] << "_LOC_MINMAX";
+    tag_name = ss_tag_name.str();
+    Tag tagh = 0;
+    std::vector<int> val(2, 0);
+    if (ijdimNames[i] == "__slon") {
+      val[0] = lDims[0];
+      val[1] = lDims[3];
+    }
+    else if (ijdimNames[i] == "__slat") {
+      val[0] = lDims[1];
+      val[1] = lDims[4];
+    }
+    else if (ijdimNames[i] == "__lon") {
+      val[0] = lCDims[0];
+      val[1] = lCDims[3];
+    }
+    else if (ijdimNames[i] == "__lat") {
+      val[0] = lCDims[1];
+      val[1] = lCDims[4];
+    }
+    rval = mbImpl->tag_get_handle(tag_name.c_str(), 2, MB_TYPE_INTEGER, tagh, MB_TAG_SPARSE | MB_TAG_CREAT);
+    ERRORR(rval, "Trouble creating __<coordinate_dim_name>_LOC_MINMAX tag.");
+    rval = mbImpl->tag_set_data(tagh, &file_set, 1, &val[0]);
+    ERRORR(rval, "Trouble setting data for __<coordinate_dim_name>_LOC_MINMAX tag.");
+    if (MB_SUCCESS == rval)
+      dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
+  }
+
+  // __<coordinate_dim_name>_GLOBAL_MINMAX
+  for (unsigned int i = 0; i != ijdimNames.size(); i++) {
+    std::stringstream ss_tag_name;
+    ss_tag_name << ijdimNames[i] << "_GLOBAL_MINMAX";
+    tag_name = ss_tag_name.str();
+    Tag tagh = 0;
+    std::vector<int> val(2, 0);
+    if (ijdimNames[i] == "__slon") {
+      val[0] = gDims[0];
+      val[1] = gDims[3];
+    }
+    else if (ijdimNames[i] == "__slat") {
+      val[0] = gDims[1];
+      val[1] = gDims[4];
+    }
+    else if (ijdimNames[i] == "__lon") {
+      val[0] = gCDims[0];
+      val[1] = gCDims[3];
+    }
+    else if (ijdimNames[i] == "__lat") {
+      val[0] = gCDims[1];
+      val[1] = gCDims[4];
+    }
+    rval = mbImpl->tag_get_handle(tag_name.c_str(), 2, MB_TYPE_INTEGER, tagh, MB_TAG_SPARSE | MB_TAG_CREAT);
+    ERRORR(rval, "Trouble creating __<coordinate_dim_name>_GLOBAL_MINMAX tag.");
+    rval = mbImpl->tag_set_data(tagh, &file_set, 1, &val[0]);
+    ERRORR(rval, "Trouble setting data for __<coordinate_dim_name>_GLOBAL_MINMAX tag.");
+    if (MB_SUCCESS == rval)
+      dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
+  }
+
+  // hack: create dummy tags, if needed, for dimensions like nbnd
+  // with no corresponding variables
+  _readNC->init_dims_with_no_cvars_info();
+
+  return MB_SUCCESS;
+}
+
+ErrorCode NCHelperFV::create_verts_quads(ScdInterface* scdi, const FileOptions& opts, EntityHandle file_set, Range& quads)
+{
+  return _readNC->create_scd_verts_quads(scdi, file_set, quads);
+}
+
+} // namespace moab

diff --git a/src/io/NCHelperFV.hpp b/src/io/NCHelperFV.hpp
new file mode 100644
index 0000000..afcd9b8
--- /dev/null
+++ b/src/io/NCHelperFV.hpp
@@ -0,0 +1,32 @@
+//-------------------------------------------------------------------------
+// Filename      : NCHelperFV.hpp
+//
+// Purpose       : Climate NC file helper for Finite Volume grid
+//
+// Creator       : Danqing Wu
+//-------------------------------------------------------------------------
+
+#ifndef NCHELPERFV_HPP
+#define NCHELPERFV_HPP
+
+#include "NCHelper.hpp"
+
+namespace moab {
+
+//! Child helper class for Finite Volume grid (CAM_FV)
+class NCHelperFV : public NCHelper
+{
+public:
+  NCHelperFV(ReadNC* readNC, int fileId) : NCHelper(readNC, fileId) {}
+  static bool can_read_file(ReadNC* readNC, int fileId);
+
+private:
+  virtual ErrorCode init_mesh_vals(const FileOptions& opts, EntityHandle file_set);
+  virtual ErrorCode create_verts_quads(ScdInterface* scdi, const FileOptions& opts, EntityHandle file_set, Range& quads);
+  virtual std::string get_mesh_type_name() { return "CAM_FV"; }
+  virtual bool is_scd_mesh() { return true; }
+};
+
+} // namespace moab
+
+#endif

diff --git a/src/io/NCHelperHOMME.cpp b/src/io/NCHelperHOMME.cpp
new file mode 100644
index 0000000..32faa58
--- /dev/null
+++ b/src/io/NCHelperHOMME.cpp
@@ -0,0 +1,506 @@
+#include "NCHelperHOMME.hpp"
+#include "moab/ReadUtilIface.hpp"
+#include "FileOptions.hpp"
+#include "moab/SpectralMeshTool.hpp"
+
+#include <cmath>
+
+#define ERRORR(rval, str) \
+    if (MB_SUCCESS != rval) {_readNC->readMeshIface->report_error("%s", str); return rval;}
+
+#define ERRORS(err, str) \
+    if (err) {_readNC->readMeshIface->report_error("%s", str); return MB_FAILURE;}
+
+namespace moab {
+
+NCHelperHOMME::NCHelperHOMME(ReadNC* readNC, int fileId, const FileOptions& opts) : NCHelper(readNC, fileId), _spectralOrder(-1)
+{
+  // Calculate spectral order
+  std::map<std::string, ReadNC::AttData>::iterator attIt = readNC->globalAtts.find("np");
+  if (attIt != readNC->globalAtts.end()) {
+    int success = NCFUNC(get_att_int)(readNC->fileId, attIt->second.attVarId, attIt->second.attName.c_str(), &_spectralOrder);
+    if (success != 0)
+      readNC->readMeshIface->report_error("%s", "Failed to read np global attribute int data.");
+    else
+      _spectralOrder--; // Spectral order is one less than np
+
+    if (MB_SUCCESS == opts.match_option("PARTITION_METHOD", "NODAL_PARTITION"))
+      readNC->partMethod = -1;
+  }
+}
+
+bool NCHelperHOMME::can_read_file(ReadNC* readNC, int fileId)
+{
+  // If global attribute "np" exists then it should be the HOMME grid
+  if (readNC->globalAtts.find("np") != readNC->globalAtts.end()) {
+    // Make sure it is CAM grid
+    std::map<std::string, ReadNC::AttData>::iterator attIt = readNC->globalAtts.find("source");
+    if (attIt == readNC->globalAtts.end()) {
+      readNC->readMeshIface->report_error("%s", "File does not have source global attribute.");
+      return false;
+    }
+    unsigned int sz = attIt->second.attLen;
+    std::string att_data;
+    att_data.resize(sz + 1);
+    att_data[sz] = '\000';
+    int success = NCFUNC(get_att_text)(fileId, attIt->second.attVarId, attIt->second.attName.c_str(), &att_data[0]);
+    if (success != 0) {
+      readNC->readMeshIface->report_error("%s", "Failed to read source global attribute char data.");
+      return false;
+    }
+    if (att_data.find("CAM") == std::string::npos)
+      return false;
+
+    return true;
+  }
+
+  return false;
+}
+
+ErrorCode NCHelperHOMME::init_mesh_vals(const FileOptions& opts, EntityHandle file_set)
+{
+  std::vector<std::string>& dimNames = _readNC->dimNames;
+  std::vector<int>& dimVals = _readNC->dimVals;
+  std::string& kName = _readNC->kName;
+  std::string& tName = _readNC->tName;
+  std::map<std::string, ReadNC::VarData>& varInfo = _readNC->varInfo;
+  int& tMin = _readNC->tMin;
+  int& tMax = _readNC->tMax;
+  int (&gDims)[6] = _readNC->gDims;
+  int (&lDims)[6] = _readNC->lDims;
+  int& iDim = _readNC->iDim;
+  int& kDim = _readNC->kDim;
+  int& tDim = _readNC->tDim;
+  std::vector<double>& ilVals = _readNC->ilVals;
+  std::vector<double>& jlVals = _readNC->jlVals;
+  std::vector<double>& klVals = _readNC->klVals;
+  std::vector<double>& tVals = _readNC->tVals;
+
+  ErrorCode rval;
+  unsigned int idx;
+  std::vector<std::string>::iterator vit;
+  if ((vit = std::find(dimNames.begin(), dimNames.end(), "time")) != dimNames.end())
+    idx = vit - dimNames.begin();
+  else if ((vit = std::find(dimNames.begin(), dimNames.end(), "t")) != dimNames.end())
+    idx = vit - dimNames.begin();
+  else {
+    ERRORR(MB_FAILURE, "Couldn't find time variable.");
+  }
+  tDim = idx;
+  tMax = dimVals[idx] - 1;
+  tMin = 0;
+  tName = dimNames[idx];
+
+  // get number of vertices (labeled as number of columns) and levels
+  gDims[0] = gDims[3] = -1;
+  if ((vit = std::find(dimNames.begin(), dimNames.end(), "ncol")) != dimNames.end()) {
+    idx = vit - dimNames.begin();
+    gDims[3] = dimVals[idx] - 1;
+    gDims[0] = 0;
+    iDim = idx;
+  }
+  if (-1 == gDims[0])
+    return MB_FAILURE;
+
+  // set j coordinate to the number of quads
+  gDims[1] = gDims[0];
+  gDims[4] = gDims[3] - 2;
+
+  gDims[2] = gDims[5] = -1;
+  if ((vit = std::find(dimNames.begin(), dimNames.end(), "lev")) != dimNames.end()) {
+    idx = vit - dimNames.begin();
+    gDims[5] = dimVals[idx] - 1, gDims[2] = 0, kName = std::string("lev");
+    kDim = idx;
+  }
+  if (-1 == gDims[2])
+    return MB_FAILURE;
+
+  // read coordinate data
+  std::map<std::string, ReadNC::VarData>::iterator vmit;
+  if (gDims[0] != -1) {
+    if ((vmit = varInfo.find("lon")) != varInfo.end() && (*vmit).second.varDims.size() == 1) {
+      rval = _readNC->read_coordinate("lon", gDims[0], gDims[3], ilVals);
+      ERRORR(rval, "Trouble reading x variable.");
+    }
+    else {
+      ERRORR(MB_FAILURE, "Couldn't find x coordinate.");
+    }
+  }
+
+  // store lat values in jlVals parameterized by j
+  if (gDims[1] != -1) {
+    if ((vmit = varInfo.find("lat")) != varInfo.end() && (*vmit).second.varDims.size() == 1) {
+      rval = _readNC->read_coordinate("lat", gDims[0], gDims[3], jlVals);
+      ERRORR(rval, "Trouble reading y variable.");
+    }
+    else {
+      ERRORR(MB_FAILURE, "Couldn't find y coordinate.");
+    }
+  }
+
+  if (gDims[2] != -1) {
+    if ((vmit = varInfo.find("lev")) != varInfo.end() && (*vmit).second.varDims.size() == 1) {
+      rval = _readNC->read_coordinate("lev", gDims[2], gDims[5], klVals);
+      ERRORR(rval, "Trouble reading z variable.");
+
+      // decide whether down is positive
+      char posval[10];
+      int success = NCFUNC(get_att_text)(_readNC->fileId, (*vmit).second.varId, "positive", posval);
+      if (0 == success && !strcmp(posval, "down")) {
+        for (std::vector<double>::iterator dvit = klVals.begin(); dvit != klVals.end(); ++dvit)
+          (*dvit) *= -1.0;
+      }
+    }
+    else {
+      ERRORR(MB_FAILURE, "Couldn't find z coordinate.");
+    }
+  }
+
+  if (tMin != -1) {
+    if ((vmit = varInfo.find(tName)) != varInfo.end() && (*vmit).second.varDims.size() == 1) {
+      rval = _readNC->read_coordinate(tName.c_str(), tMin, tMax, tVals);
+      ERRORR(rval, "Trouble reading time variable.");
+    }
+    else {
+      ERRORR(MB_FAILURE, "Couldn't find time coordinate.");
+    }
+  }
+
+  if ((vmit = varInfo.find(tName)) != varInfo.end() && (*vmit).second.varDims.size() == 1) {
+    rval = _readNC->read_coordinate(tName.c_str(), tMin, tMax, tVals);
+    ERRORR(rval, "Trouble reading time variable.");
+  }
+  else {
+    ERRORR(MB_FAILURE, "Couldn't find time coordinate.");
+  }
+
+  // determine the entity location type of a variable
+  std::map<std::string, ReadNC::VarData>::iterator mit;
+  for (mit = varInfo.begin(); mit != varInfo.end(); ++mit) {
+    ReadNC::VarData& vd = (*mit).second;
+    if ((std::find(vd.varDims.begin(), vd.varDims.end(), iDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(),
+        vd.varDims.end(), kDim) != vd.varDims.end()))
+      vd.entLoc = ReadNC::ENTLOCNODE;
+  }
+
+  std::copy(gDims, gDims + 6, lDims);
+
+  // don't read coordinates of columns until we actually create the mesh
+
+  // hack: create dummy tags, if needed, for variables like ncol and nbnd
+  // with no corresponding variables
+  _readNC->init_dims_with_no_cvars_info();
+
+  // This check is for HOMME and other ucd mesh. When ReadNC class instance
+  // gets out of scope in a script (and deleted), the localGid will be lost
+  rval = _readNC->check_ucd_localGid(file_set);
+  ERRORR(rval, "Trouble checking local Gid for ucd mesh.");
+
+  return MB_SUCCESS;
+}
+
+ErrorCode NCHelperHOMME::create_verts_quads(ScdInterface* scdi, const FileOptions& opts, EntityHandle file_set, Range& quads)
+{
+  Interface*& mbImpl = _readNC->mbImpl;
+  std::string& fileName = _readNC->fileName;
+  int& connectId = _readNC->connectId;
+  int (&gDims)[6] = _readNC->gDims;
+  int (&lDims)[6] = _readNC->lDims;
+  std::vector<double>& ilVals = _readNC->ilVals;
+  std::vector<double>& jlVals = _readNC->jlVals;
+  std::vector<double>& klVals = _readNC->klVals;
+  Tag& mGlobalIdTag = _readNC->mGlobalIdTag;
+  const Tag*& mpFileIdTag = _readNC->mpFileIdTag;
+  DebugOutput& dbgOut = _readNC->dbgOut;
+  bool& isParallel = _readNC->isParallel;
+  Range& localGid = _readNC->localGid;
+#ifdef USE_MPI
+  ParallelComm*& myPcomm = _readNC->myPcomm;
+#endif
+  bool& spectralMesh = _readNC->spectralMesh;
+
+  // need to get/read connectivity data before creating elements
+  std::string conn_fname;
+
+  // try to open the connectivity file through CONN option, if used
+  ErrorCode rval = opts.get_str_option("CONN", conn_fname);
+  if (MB_SUCCESS != rval) {
+    // default convention for reading HOMME is a file HommeMapping.nc in same dir as data file
+    conn_fname = std::string(fileName);
+    size_t idx = conn_fname.find_last_of("/");
+    if (idx != std::string::npos)
+      conn_fname = conn_fname.substr(0, idx).append("/HommeMapping.nc");
+    else
+      conn_fname = "HommeMapping.nc";
+  }
+
+  int success;
+
+  int rank, procs;
+#ifdef PNETCDF_FILE
+  if (isParallel) {
+    success = NCFUNC(open)(myPcomm->proc_config().proc_comm(), conn_fname.c_str(), 0, MPI_INFO_NULL, &connectId);
+    rank = myPcomm->proc_config().proc_rank();
+    procs = myPcomm->proc_config().proc_size();
+  }
+  else {
+    success = NCFUNC(open)(MPI_COMM_SELF, conn_fname.c_str(), 0, MPI_INFO_NULL, &connectId);
+    rank = 0;
+    procs = 1;
+  }
+#else
+  success = NCFUNC(open)(conn_fname.c_str(), 0, &connectId);
+  rank = 0;
+  procs = 1;
+#endif
+  ERRORS(success, "Failed on open.");
+
+  std::vector<std::string> conn_names;
+  std::vector<int> conn_vals;
+  rval = _readNC->get_dimensions(connectId, conn_names, conn_vals);
+  ERRORR(rval, "Failed to get dimensions for connectivity.");
+
+  if (conn_vals[0] != gDims[3] - gDims[0] + 1 - 2) {
+    dbgOut.tprintf(1, "Warning: number of quads from %s and vertices from %s are inconsistent; nverts = %d, nquads = %d.\n",
+        conn_fname.c_str(), fileName.c_str(), gDims[3] - gDims[0] + 1, conn_vals[0]);
+  }
+
+  // read connectivity into temporary variable
+  int num_fine_quads, num_coarse_quads, start_idx;
+  std::vector<std::string>::iterator vit;
+  int idx;
+  if ((vit = std::find(conn_names.begin(), conn_names.end(), "ncells")) != conn_names.end())
+    idx = vit - conn_names.begin();
+  else if ((vit = std::find(conn_names.begin(), conn_names.end(), "ncenters")) != conn_names.end())
+    idx = vit - conn_names.begin();
+  else {
+    ERRORR(MB_FAILURE, "Failed to get number of quads.");
+  }
+  int num_quads = conn_vals[idx];
+
+  // get the connectivity into tmp_conn2 and permute into tmp_conn
+  int cornerVarId;
+  success = NCFUNC(inq_varid)(connectId, "element_corners", &cornerVarId);
+  ERRORS(success, "Failed to get variable id.");
+  NCDF_SIZE tmp_dims[2] = {0, 0}, tmp_counts[2] = {4, static_cast<size_t>(num_quads)};
+  std::vector<int> tmp_conn(4 * num_quads), tmp_conn2(4 * num_quads);
+  success = NCFUNCAG(_vara_int)(connectId, cornerVarId, tmp_dims, tmp_counts, &tmp_conn2[0] NCREQ);
+  ERRORS(success, "Failed to get temporary connectivity.");
+  success = NCFUNC(close)(connectId);
+  ERRORS(success, "Failed on close.");
+  // permute the connectivity
+  for (int i = 0; i < num_quads; i++) {
+    tmp_conn[4 * i] = tmp_conn2[i];
+    tmp_conn[4 * i + 1] = tmp_conn2[i + 1 * num_quads];
+    tmp_conn[4 * i + 2] = tmp_conn2[i + 2 * num_quads];
+    tmp_conn[4 * i + 3] = tmp_conn2[i + 3 * num_quads];
+  }
+
+  // need to know whether we'll be creating gather mesh later, to make sure we allocate enough space
+  // in one shot
+  bool create_gathers = true;
+#ifdef USE_MPI
+  if (isParallel)
+    if (myPcomm->proc_config().proc_rank() != 0)
+      create_gathers = false;
+#endif
+
+  // compute the number of local quads, accounting for coarse or fine representation
+  // spectral_unit is the # fine quads per coarse quad, or spectralOrder^2
+  int spectral_unit = (spectralMesh ? _spectralOrder * _spectralOrder : 1);
+  // num_coarse_quads is the number of quads instantiated in MOAB; if !spectralMesh, num_coarse_quads = num_fine_quads
+  num_coarse_quads = int(std::floor(1.0 * num_quads / (spectral_unit * procs)));
+  // start_idx is the starting index in the HommeMapping connectivity list for this proc, before converting to coarse quad representation
+  start_idx = 4 * rank * num_coarse_quads * spectral_unit;
+  // iextra = # coarse quads extra after equal split over procs
+  int iextra = num_quads % (procs * spectral_unit);
+  if (rank < iextra)
+    num_coarse_quads++;
+  start_idx += 4 * spectral_unit * std::min(rank, iextra);
+  // num_fine_quads is the number of quads in the connectivity list in HommeMapping file assigned to this proc
+  num_fine_quads = spectral_unit * num_coarse_quads;
+
+  // now create num_coarse_quads
+  EntityHandle *conn_arr;
+  EntityHandle start_vertex;
+  Range tmp_range;
+
+  // read connectivity into that space
+  EntityHandle *sv_ptr = NULL, start_quad;
+  SpectralMeshTool smt(mbImpl, _spectralOrder);
+  if (!spectralMesh) {
+    rval = _readNC->readMeshIface->get_element_connect(num_coarse_quads, 4,
+                                              MBQUAD, 0, start_quad, conn_arr,
+                                                // might have to create gather mesh later
+                                              (create_gathers ? num_coarse_quads + num_quads : num_coarse_quads));
+    ERRORR(rval, "Failed to create quads.");
+    tmp_range.insert(start_quad, start_quad + num_coarse_quads - 1);
+    std::copy(&tmp_conn[start_idx], &tmp_conn[start_idx + 4 * num_fine_quads], conn_arr);
+    std::copy(conn_arr, conn_arr + 4 * num_fine_quads, range_inserter(localGid));
+  }
+  else {
+    rval = smt.create_spectral_elems(&tmp_conn[0], num_fine_quads, 2, tmp_range, start_idx, &localGid);
+    ERRORR(rval, "Failed to create spectral elements.");
+    int count, v_per_e;
+    rval = mbImpl->connect_iterate(tmp_range.begin(), tmp_range.end(), conn_arr, v_per_e, count);
+    ERRORR(rval, "Failed to get connectivity of spectral elements.");
+    rval = mbImpl->tag_iterate(smt.spectral_vertices_tag(true), tmp_range.begin(), tmp_range.end(),
+                               count, (void*&)sv_ptr);
+    ERRORR(rval, "Failed to get fine connectivity of spectral elements.");
+  }
+
+  // on this proc, I get columns ldims[1]..ldims[4], inclusive; need to find which vertices those correpond to
+  unsigned int num_local_verts = localGid.size();
+  unsigned int num_total_verts = gDims[3] - gDims[0] + 1;
+
+  // create vertices
+  std::vector<double*> arrays;
+  rval = _readNC->readMeshIface->get_node_coords(3, num_local_verts, 0, start_vertex, arrays,
+                                          // might have to create gather mesh later
+                                        (create_gathers ? num_local_verts+num_total_verts : num_local_verts));
+  ERRORR(rval, "Couldn't create vertices in ucd mesh.");
+
+  // set vertex coordinates
+  Range::iterator rit;
+  double *xptr = arrays[0], *yptr = arrays[1], *zptr = arrays[2];
+  int i;
+  for (i = 0, rit = localGid.begin(); i < (int)num_local_verts; i++, ++rit) {
+    assert(*rit < ilVals.size() + 1);
+    xptr[i] = ilVals[(*rit) - 1];
+    yptr[i] = jlVals[(*rit) - 1];
+    zptr[i] = klVals[lDims[2]];
+  }
+
+  const double pideg = acos(-1.0) / 180.0;
+  for (i = 0; i < (int)num_local_verts; i++) {
+    double cosphi = cos(pideg * yptr[i]);
+    double zmult = sin(pideg * yptr[i]), xmult = cosphi * cos(xptr[i] * pideg), ymult = cosphi * sin(xptr[i] * pideg);
+    double rad = 8.0e3 + klVals[lDims[2]];
+    xptr[i] = rad * xmult, yptr[i] = rad * ymult, zptr[i] = rad * zmult;
+  }
+
+  // get ptr to gid memory for vertices
+  Range vert_range(start_vertex, start_vertex + num_local_verts - 1);
+  void *data;
+  int count;
+  rval = mbImpl->tag_iterate(mGlobalIdTag, vert_range.begin(), vert_range.end(), count, data);
+  ERRORR(rval, "Failed to get tag iterator.");
+  assert(count == (int) num_local_verts);
+  int *gid_data = (int*) data;
+  std::copy(localGid.begin(), localGid.end(), gid_data);
+  // duplicate global id data, which will be used to resolve sharing
+  if (mpFileIdTag) {
+    rval = mbImpl->tag_iterate(*mpFileIdTag, vert_range.begin(), vert_range.end(), count, data);
+    ERRORR(rval, "Failed to get tag iterator on file id tag.");
+    assert(count == (int) num_local_verts);
+    gid_data = (int*) data;
+    std::copy(localGid.begin(), localGid.end(), gid_data);
+  }
+
+  // create map from file ids to vertex handles, used later to set connectivity
+  std::map<EntityHandle, EntityHandle> vert_handles;
+  for (rit = localGid.begin(), i = 0; rit != localGid.end(); ++rit, i++) {
+    vert_handles[*rit] = start_vertex + i;
+  }
+
+  // compute proper handles in connectivity using offset
+  for (int q = 0; q < 4 * num_coarse_quads; q++) {
+    conn_arr[q] = vert_handles[conn_arr[q]];
+    assert(conn_arr[q]);
+  }
+  if (spectralMesh) {
+    int verts_per_quad = (_spectralOrder + 1) * (_spectralOrder + 1);
+    for (int q = 0; q < verts_per_quad * num_coarse_quads; q++) {
+      sv_ptr[q] = vert_handles[sv_ptr[q]];
+      assert(sv_ptr[q]);
+    }
+  }
+
+  // add new vertices and elements to the set
+  quads.merge(tmp_range);
+  tmp_range.insert(start_vertex, start_vertex + num_local_verts - 1);
+  rval = mbImpl->add_entities(file_set, tmp_range);
+  ERRORR(rval, "Couldn't add new vertices and quads/hexes to file set.");
+
+  // mark the set with the spectral order
+  Tag sporder;
+  rval = mbImpl->tag_get_handle("SPECTRAL_ORDER", 1, MB_TYPE_INTEGER, sporder, MB_TAG_CREAT | MB_TAG_SPARSE);
+  ERRORR(rval, "Couldn't create spectral order tag.");
+  rval = mbImpl->tag_set_data(sporder, &file_set, 1, &_spectralOrder);
+  ERRORR(rval, "Couldn't set value for spectral order tag.");
+
+#ifdef USE_MPI
+  if (isParallel && myPcomm->proc_config().proc_rank() == 0) {
+#endif
+    EntityHandle gather_set;
+    rval = mbImpl->create_meshset(MESHSET_SET, gather_set);
+    ERRORR(rval, "Trouble creating gather set.");
+
+    // create vertices
+    arrays.clear();
+    // don't need to specify allocation number here, because we know enough verts were created before
+    rval = _readNC->readMeshIface->get_node_coords(3, num_total_verts, 0, start_vertex, arrays);
+    ERRORR(rval, "Couldn't create vertices in ucd mesh for gather set.");
+
+    xptr = arrays[0], yptr = arrays[1], zptr = arrays[2];
+    for (i = 0; i < (int)num_total_verts; i++) {
+      double cosphi = cos(pideg * jlVals[i]);
+      double zmult = sin(pideg * jlVals[i]);
+      double xmult = cosphi * cos(ilVals[i] * pideg);
+      double ymult = cosphi * sin(ilVals[i] * pideg);
+      double rad = 8.0e3 + klVals[lDims[2]];
+      xptr[i] = rad * xmult;
+      yptr[i] = rad * ymult;
+      zptr[i] = rad * zmult;
+    }
+
+    // get ptr to gid memory for vertices
+    Range gather_verts(start_vertex, start_vertex + num_total_verts - 1);
+    rval = mbImpl->tag_iterate(mGlobalIdTag, gather_verts.begin(), gather_verts.end(), count, data);
+    ERRORR(rval, "Failed to get tag iterator.");
+    assert(count == (int) num_total_verts);
+    gid_data = (int*) data;
+    for (int j = 1; j <= (int) num_total_verts; j++)
+      gid_data[j - 1] = j;
+    // set the file id tag too, it should be bigger something not interfering with global id
+    if (mpFileIdTag) {
+      rval = mbImpl->tag_iterate(*mpFileIdTag, gather_verts.begin(), gather_verts.end(), count, data);
+      ERRORR(rval, "Failed to get tag iterator in file id tag.");
+      assert(count == (int) num_total_verts);
+      gid_data = (int*) data;
+      for (int j = 1; j <= (int) num_total_verts; j++)
+        gid_data[j - 1] = num_total_verts + j; // bigger than global id tag
+    }
+
+    rval = mbImpl->add_entities(gather_set, gather_verts);
+    ERRORR(rval, "Couldn't add vertices to gather set.");
+
+    // create quads
+    Range gather_quads;
+    // don't need to specify allocation number here, because we know enough quads were created before
+    rval = _readNC->readMeshIface->get_element_connect(num_quads, 4,
+                                              MBQUAD, 0, start_quad, conn_arr);
+    ERRORR(rval, "Failed to create quads.");
+    gather_quads.insert(start_quad, start_quad + num_quads - 1);
+    std::copy(&tmp_conn[0], &tmp_conn[4 * num_quads], conn_arr);
+    for (i = 0; i != 4 * num_quads; i++)
+      conn_arr[i] += start_vertex - 1; // connectivity array is shifted by where the gather verts start
+    rval = mbImpl->add_entities(gather_set, gather_quads);
+    ERRORR(rval, "Couldn't add quads to gather set.");
+
+    Tag gathersettag;
+    rval = mbImpl->tag_get_handle("GATHER_SET", 1, MB_TYPE_INTEGER, gathersettag,
+				  MB_TAG_CREAT | MB_TAG_SPARSE);
+    ERRORR(rval, "Couldn't create gather set tag.");
+    int gatherval = 1;
+    rval = mbImpl->tag_set_data(gathersettag, &gather_set, 1, &gatherval);
+    ERRORR(rval, "Couldn't set value for gather set tag.");
+
+#ifdef USE_MPI
+  }
+#endif
+
+  return MB_SUCCESS;
+}
+
+} // namespace moab

diff --git a/src/io/NCHelperHOMME.hpp b/src/io/NCHelperHOMME.hpp
new file mode 100644
index 0000000..feb3cad
--- /dev/null
+++ b/src/io/NCHelperHOMME.hpp
@@ -0,0 +1,35 @@
+//-------------------------------------------------------------------------
+// Filename      : NCHelperHOMME.hpp
+//
+// Purpose       : Climate NC file helper for HOMME grid
+//
+// Creator       : Danqing Wu
+//-------------------------------------------------------------------------
+
+#ifndef NCHELPERHOMME_HPP
+#define NCHELPERHOMME_HPP
+
+#include "NCHelper.hpp"
+
+namespace moab {
+
+//! Child helper class for HOMME grid (CAM_SE)
+class NCHelperHOMME : public NCHelper
+{
+public:
+  NCHelperHOMME(ReadNC* readNC, int fileId, const FileOptions& opts);
+  static bool can_read_file(ReadNC* readNC, int fileId);
+
+private:
+  virtual ErrorCode init_mesh_vals(const FileOptions& opts, EntityHandle file_set);
+  virtual ErrorCode create_verts_quads(ScdInterface* scdi, const FileOptions& opts, EntityHandle file_set, Range& quads);
+  virtual std::string get_mesh_type_name() { return "CAM_SE"; }
+  virtual bool is_scd_mesh() { return false; }
+
+private:
+  int _spectralOrder; // read from variable 'np'
+};
+
+} // namespace moab
+
+#endif

This diff is so big that we needed to truncate the remainder.

https://bitbucket.org/fathomteam/moab/commits/c930858aaae5/
Changeset:   c930858aaae5
Branch:      None
User:        tautges
Date:        2013-06-12 19:00:35
Summary:     Merged fathomteam/moab into master
Affected #:  4 files

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index dc89d66..38b4130 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -38,6 +38,7 @@
     ScdVertexData.cpp
     SequenceData.cpp
     SequenceManager.cpp
+    SetIterator.cpp
     Skinner.cpp
     SparseTag.cpp
     StructuredElementSeq.cpp
@@ -46,6 +47,7 @@
     SweptVertexData.cpp
     SysUtil.cpp
     TagInfo.cpp
+    Types.cpp
     TypeSequenceManager.cpp
     UnstructuredElemSeq.cpp
     Util.cpp
@@ -53,7 +55,6 @@
     VarLenSparseTag.cpp
     VertexSequence.cpp
     WriteUtil.cpp
-    moab_mpe.c
   )
   include_directories(
     ${MOAB_SOURCE_DIR}/src

diff --git a/src/ScdInterface.cpp b/src/ScdInterface.cpp
index 24e62c3..6c79a3e 100644
--- a/src/ScdInterface.cpp
+++ b/src/ScdInterface.cpp
@@ -7,12 +7,12 @@
 #include "ScdVertexData.hpp"
 #ifdef USE_MPI
 #  include "moab/ParallelComm.hpp"
+#  include "moab/TupleList.hpp"
+#  include "moab/gs.hpp"
 #endif
 #include "assert.h"
 #include <iostream>
 #include <functional>
-#include "moab/TupleList.hpp"
-#include "moab/gs.hpp"
 
 #define ERRORR(rval, str) {if (MB_SUCCESS != rval)          \
       {std::cerr << str; return rval; }}

diff --git a/src/io/CMakeLists.txt b/src/io/CMakeLists.txt
index f83eb4f..d6c3e44 100644
--- a/src/io/CMakeLists.txt
+++ b/src/io/CMakeLists.txt
@@ -12,7 +12,9 @@
     ReadSmf.cpp
     ReadSms.cpp
     ReadSTL.cpp
+    ReadTemplate.cpp
     ReadTetGen.cpp
+    ReadTxt.cpp
     ReadVtk.cpp
     SMF_State.cpp
     Tqdcfr.cpp

diff --git a/src/moab/moabUG.h b/src/moab/moabUG.h
index afbb505..8efd863 100644
--- a/src/moab/moabUG.h
+++ b/src/moab/moabUG.h
@@ -116,9 +116,9 @@ The MOAB data model describes the basic types used in MOAB and the language used
  \ref contents
 
  \subsection twoone 2.1. MOAB Interface
-MOAB is written in C++.  The primary interface with applications is through member functions of the abstract base class Interface.  The MOAB library is created by instantiating Core, which implements the Interface API.  Multiple instances of MOAB can exist concurrently in the same application; mesh entities are not shared between these instancesi<sup>1</sup>.  MOAB is most easily viewed as a database of mesh objects accessed through the instance.  No other assumptions explicitly made about the nature of the mesh stored there; for example, there is no fundamental requirement that elements fill space or do not overlap each other geometrically.
+MOAB is written in C++.  The primary interface with applications is through member functions of the abstract base class Interface.  The MOAB library is created by instantiating Core, which implements the Interface API.  Multiple instances of MOAB can exist concurrently in the same application; mesh entities are not shared between these instancesi<sup>2</sup>.  MOAB is most easily viewed as a database of mesh objects accessed through the instance.  No other assumptions explicitly made about the nature of the mesh stored there; for example, there is no fundamental requirement that elements fill space or do not overlap each other geometrically.
  
-<sup>1</sup> One exception to this statement is when the parallel interface to MOAB is used; in this case, entity sharing between instances is handled explicitly using message passing.  This is described in more detail in Section 5 of this document.
+<sup>2</sup> One exception to this statement is when the parallel interface to MOAB is used; in this case, entity sharing between instances is handled explicitly using message passing.  This is described in more detail in Section 5 of this document.
 
  \ref contents
 
@@ -279,8 +279,8 @@ The MOAB API is designed to balance complexity and ease of use.  This balance is
 Since these objectives are at odds with each other, tradeoffs had to be made between them.  Some specific issues that came up are:
 
 - Using ranges: Where possible, entities can be referenced using either ranges (which allow efficient storage of long lists) or STL vectors (which allow list order to be preserved), in both input and output arguments.
-- Entities in sets: Accessing the entities in a set is done using the same functions which access entities in the entire mesh.  The whole mesh is referenced by specifying a set handle of zero<sup>1</sup>.
-- Entity vectors on input: Functions which could normally take a single entity as input are specified to take a vector of handles instead.  Single entities are specified by taking the address of that entity handle and specifying a list length of one.  This minimizes the number of functions, while preserving the ability to input single entities.<sup>2</sup>
+- Entities in sets: Accessing the entities in a set is done using the same functions which access entities in the entire mesh.  The whole mesh is referenced by specifying a set handle of zero<sup>3</sup>.
+- Entity vectors on input: Functions which could normally take a single entity as input are specified to take a vector of handles instead.  Single entities are specified by taking the address of that entity handle and specifying a list length of one.  This minimizes the number of functions, while preserving the ability to input single entities.<sup>4</sup>
 .
 
 Table 2 lists basic data types and enumerated variables defined and used by MOAB.  Values of the ErrorCode enumeration are returned from most MOAB functions, and can be compared to those listed in Appendix [ref-appendix].
@@ -398,9 +398,9 @@ Table 3 lists the various groups of functions that comprise the MOAB API.  This
 </tr></table>
 
-<sup>1</sup>In iMesh, the whole mesh is specified by a special entity set handle, referred to as the “root set”.
+<sup>3</sup>In iMesh, the whole mesh is specified by a special entity set handle, referred to as the “root set”.
 
-<sup>2</sup>Note that STL vectors of entity handles can be input in this manner by using &vector[0] and vector.size() for the 1d vector address and size, respectively.
+<sup>4</sup>Note that STL vectors of entity handles can be input in this manner by using &vector[0] and vector.size() for the 1d vector address and size, respectively.
 
  \ref contents
 
@@ -857,9 +857,9 @@ MOAB’s native interface is accessed through the Interface abstract C++ base cl
 
 <B>SPARSE tags used by default:</B> MOAB’s iMesh implementation creates SPARSE tags by default, because of semantic requirements of other tag-related functions in iMesh.  To create DENSE tags through iMesh, use the iMesh_createTagWithOptions extension function (see below).
 
-<B>Higher-order elements:</B> ITAPS currently handles higher-order elements (e.g. a 10-node tetrahedron) usi[21]<sup>1</sup>.  As described in [sec-entities], MOAB supports higher-order entities by allowing various numbers of vertices to define topological entities like quadrilateral or tetrahedron.  Applications can specify flags to the connectivity and adjacency functions specifying whether corner or all vertices are requested.
+<B>Higher-order elements:</B> ITAPS currently handles higher-order elements (e.g. a 10-node tetrahedron) usi[21]<sup>5</sup>.  As described in [sec-entities], MOAB supports higher-order entities by allowing various numbers of vertices to define topological entities like quadrilateral or tetrahedron.  Applications can specify flags to the connectivity and adjacency functions specifying whether corner or all vertices are requested.
 
-<B>Self-adjacencies:</B> In MOAB’s native interface, entities are always self-adjacent<sup>2</sup>; that is, adjacencies of equal dimension requested from an entity will always include that entity, while from iMesh will not include that entity.
+<B>Self-adjacencies:</B> In MOAB’s native interface, entities are always self-adjacent<sup>6</sup>; that is, adjacencies of equal dimension requested from an entity will always include that entity, while from iMesh will not include that entity.
 
 <B>Option strings:</B> The iMesh specification requires that options in the options string passed to various functions (e.g. iMesh_load) be prepended with the implementation name required to parse them, and delimited with spaces.  Thus, a MOAB-targeted option would appear as “moab:PARALLEL=READ_PART moab:PARTITION=MATERIAL_SET”.
 
@@ -882,19 +882,19 @@ As required by the iMesh specification, MOAB generates the “iMesh-Defs.inc”
 
 Note that using the iMesh interface from Fortran-based applications requires a compiler that supports Cray pointers, along with the pass-by-value (%VAL) extension.  Almost all compilers support those extensions; however, if using the gcc series of compilers, you must use gfortran 4.3 or later.
 
-<sup>1</sup>There are currently no implementations of this interface.
+<sup>5</sup>There are currently no implementations of this interface.
 
-<sup>2</sup>iMesh and MOAB both define adjacencies using the topological concept of closure.  Since the closure of an entity includes the entity itself, the d-dimensional entities on the closure of a given entity should include the entity itself.
+<sup>6</sup>iMesh and MOAB both define adjacencies using the topological concept of closure.  Since the closure of an entity includes the entity itself, the d-dimensional entities on the closure of a given entity should include the entity itself.
 
  \ref contents
 
   \section representation 8. Structured Mesh Representation
 
-A structured mesh is defined as a D-dimensional mesh whose interior vertices have 2D connected edges.   Structured mesh can be stored without connectivity, if certain information is kept about the parametric space of each structured block of mesh.  MOAB can represent structured mesh with implicit connectivity, saving approximately 57% of the storage cost compared to an unstructured representation<sup>1</sup>.  Since connectivity must be computed on the fly, these queries execute a bit slower than those for unstructured mesh.  More information on the theory behind MOAB's structured mesh representation can be found in 
+A structured mesh is defined as a D-dimensional mesh whose interior vertices have 2D connected edges.   Structured mesh can be stored without connectivity, if certain information is kept about the parametric space of each structured block of mesh.  MOAB can represent structured mesh with implicit connectivity, saving approximately 57% of the storage cost compared to an unstructured representation<sup>7</sup>.  Since connectivity must be computed on the fly, these queries execute a bit slower than those for unstructured mesh.  More information on the theory behind MOAB's structured mesh representation can be found in 
 
 Currently, MOAB's structured mesh representation can only be used by creating structured mesh at runtime; that is, structured mesh is saved/restored in an unstructured format in MOAB's HDF5-based native save format.  For more details on how to use MOAB's structured mesh representation, see the scdseq_test.cpp source file in the test/ directory.
 
-<sup>1</sup> This assumes vertex coordinates are represented explicitly, and that there are approximately the same number of vertices and hexahedra in a structured hex mesh.
+<sup>7</sup> This assumes vertex coordinates are represented explicitly, and that there are approximately the same number of vertices and hexahedra in a structured hex mesh.
 
  \ref contents
 


https://bitbucket.org/fathomteam/moab/commits/1480624e6eea/
Changeset:   1480624e6eea
Branch:      None
User:        tautges
Date:        2013-06-14 21:08:43
Summary:     Big batch of smallish changes working toward performance analysis of tree stuff.  Make check runs correctly.

Fixed includes of FileOptions, indicated by an out-of-source build.
Added a cpu timer class (lifted from WriteHDF5), and added that to call stats in the trees.
Fixed problem creating multiple sets at a time, have to duplicate flags into an array instead of using just one.
Added Tree::parse_options as a required virtual function.
Added optional output() method to TreeStats to output all stats on a single line.
Added testing Makefile.am magic for test/perf/point_location subdirectory, and several new performance tests for tree stuff.
Added several options to spatial_locator_test to allow various size meshes and other options.
Fixed several places in trees (or put in asserts) that were evaluating tree root before setting it
In reverse evaluation, if not converged but are outside at time of test and inside flag returned from function, return success
Fixed a few places where connectivity requested but no dummy array input (so didn't work for scd mesh)
In SpatialLocator point search, pass in tolerance to element reverse evaluation
Fixed dumb makefile.am misspelling
sploc_searching_perf: add support for element evaluation and for tolerance

Affected #:  57 files

diff --git a/itaps/igeom/FBiGeom_MOAB.cpp b/itaps/igeom/FBiGeom_MOAB.cpp
index cb889bd..7fcd2b1 100644
--- a/itaps/igeom/FBiGeom_MOAB.cpp
+++ b/itaps/igeom/FBiGeom_MOAB.cpp
@@ -4,7 +4,7 @@
 #include "moab/GeomTopoTool.hpp"
 #include "moab/OrientedBoxTreeTool.hpp"
 #include "moab/CartVect.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "MBTagConventions.hpp"
 #include <stdlib.h>
 #include <cstring>

diff --git a/itaps/imesh/iMeshP_MOAB.cpp b/itaps/imesh/iMeshP_MOAB.cpp
index d67dfc9..6522df2 100644
--- a/itaps/imesh/iMeshP_MOAB.cpp
+++ b/itaps/imesh/iMeshP_MOAB.cpp
@@ -4,7 +4,7 @@
 #include "moab/Range.hpp"
 #include "moab/CN.hpp"
 #include "moab/MeshTopoUtil.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "moab/ParallelComm.hpp"
 #include "MBParallelConventions.h"
 #include "MBIter.hpp"

diff --git a/itaps/imesh/iMesh_MOAB.cpp b/itaps/imesh/iMesh_MOAB.cpp
index 6d55492..4f3ca90 100644
--- a/itaps/imesh/iMesh_MOAB.cpp
+++ b/itaps/imesh/iMesh_MOAB.cpp
@@ -4,7 +4,7 @@
 #include "moab/CN.hpp"
 #include "moab/MeshTopoUtil.hpp"
 #include "moab/ScdInterface.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "iMesh_MOAB.hpp"
 #include "MBIter.hpp"
 #include "MBTagConventions.hpp"

diff --git a/src/AdaptiveKDTree.cpp b/src/AdaptiveKDTree.cpp
index 6ceebc6..77f51fd 100644
--- a/src/AdaptiveKDTree.cpp
+++ b/src/AdaptiveKDTree.cpp
@@ -6,6 +6,7 @@
 #include "moab/GeomUtil.hpp"
 #include "moab/Range.hpp"
 #include "moab/ElemEvaluator.hpp"
+#include "moab/CpuTimer.hpp"
 #include "Internals.hpp"
 #include <math.h>
 
@@ -75,6 +76,7 @@ namespace moab {
                                          FileOptions *options) 
     {
       ErrorCode rval;
+      CpuTimer cp;
 
       if (options) {
         rval = parse_options(*options);
@@ -176,6 +178,7 @@ namespace moab {
           if (MB_ENTITY_NOT_FOUND == rval) {
             treeStats.reset();
             rval = treeStats.compute_stats(mbImpl, myRoot);
+            treeStats.initTime = cp.time_elapsed();
             return rval;  // at end
           }
           else if (MB_SUCCESS != rval)
@@ -1464,7 +1467,7 @@ namespace moab {
       }
   
         // begin with root in list  
-      node.handle = *tree_root;
+      node.handle = (tree_root ? *tree_root : myRoot);
       list.push_back( node );
   
       while( !list.empty() ) {
@@ -1618,6 +1621,7 @@ namespace moab {
       std::vector<EntityHandle> stack;
       std::vector<EntityHandle> children(2);
       stack.reserve(30);
+      assert(root);
       stack.push_back( root );
   
       while (!stack.empty()) {
@@ -1790,6 +1794,7 @@ namespace moab {
         // Find the leaf containing the input point
         // This search does not take into account any bounding box for the
         // tree, so it always returns one leaf.
+      assert(tree_root);
       rval = find_close_triangle( tree_root, from_coords, closest_pt.array(), triangle_out );
       if (MB_SUCCESS != rval) return rval;
   
@@ -1828,6 +1833,7 @@ namespace moab {
       int conn_len;
 
         // get leaves of tree that intersect sphere
+      assert(tree_root);
       rval = distance_search(center, radius, leaves, 0.0, NULL, NULL, &tree_root);
       if (MB_SUCCESS != rval) return rval;
   

diff --git a/src/BVHTree.cpp b/src/BVHTree.cpp
index d50f94b..8903070 100644
--- a/src/BVHTree.cpp
+++ b/src/BVHTree.cpp
@@ -2,6 +2,7 @@
 #include "moab/Interface.hpp"
 #include "moab/ElemEvaluator.hpp"
 #include "moab/ReadUtilIface.hpp"
+#include "moab/CpuTimer.hpp"
 
 namespace moab 
 {
@@ -12,6 +13,7 @@ namespace moab
                                   FileOptions *options) 
     {
       ErrorCode rval;
+      CpuTimer cp;
 
       if (options) {
         rval = parse_options(*options);
@@ -82,6 +84,7 @@ namespace moab
 
       treeStats.reset();
       rval = treeStats.compute_stats(mbImpl, startSetHandle);
+      treeStats.initTime = cp.time_elapsed();
       
       return rval;
     }
@@ -92,12 +95,15 @@ namespace moab
       ReadUtilIface *read_util;
       ErrorCode rval = mbImpl->query_interface(read_util);
       if (MB_SUCCESS != rval) return rval;
-      
-      rval = read_util->create_entity_sets(tree_nodes.size(), &meshsetFlags, 0, startSetHandle);
-      if (MB_SUCCESS != rval) return rval;
-      rval = mbImpl->release_interface(read_util);
-      if (MB_SUCCESS != rval) return rval;
 
+      {// isolate potentially-large std::vector so it gets deleted earlier
+        std::vector<unsigned int> tmp_flags(tree_nodes.size(), meshsetFlags);
+        rval = read_util->create_entity_sets(tree_nodes.size(), &tmp_flags[0], 0, startSetHandle);
+        if (MB_SUCCESS != rval) return rval;
+        rval = mbImpl->release_interface(read_util);
+        if (MB_SUCCESS != rval) return rval;
+      }
+      
         // populate the sets and the TreeNode vector
       EntityHandle set_handle = startSetHandle;
       std::vector<Node>::iterator it;

diff --git a/src/Core.cpp b/src/Core.cpp
index 8830acb..faba0f3 100644
--- a/src/Core.cpp
+++ b/src/Core.cpp
@@ -83,7 +83,7 @@
 #include "MBTagConventions.hpp"
 #include "ExoIIUtil.hpp"
 #include "EntitySequence.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #ifdef LINUX
 # include <dlfcn.h>
 # include <dirent.h>

diff --git a/src/LocalDiscretization/ElemEvaluator.cpp b/src/LocalDiscretization/ElemEvaluator.cpp
index 45851a8..b132da9 100644
--- a/src/LocalDiscretization/ElemEvaluator.cpp
+++ b/src/LocalDiscretization/ElemEvaluator.cpp
@@ -40,8 +40,14 @@ namespace moab {
       int iters=0;
         // while |res| larger than tol
       while (res % res > error_tol_sqr) {
-        if(++iters>10)
+        if(++iters>10) {
+          if (inside) {
+              // if we haven't converged but we're outside, that's defined as success
+            *inside = (*inside_f)(params, ndim, tol);
+            if (!(*inside)) return MB_SUCCESS;
+          }
           return MB_FAILURE;
+        }
 
           // get jacobian at current params
         rval = (*jacob)(cvparams->array(), verts, nverts, ndim, work, J[0]);

diff --git a/src/LocalDiscretization/moab/ElemEvaluator.hpp b/src/LocalDiscretization/moab/ElemEvaluator.hpp
index f3be3e9..48d34ac 100644
--- a/src/LocalDiscretization/moab/ElemEvaluator.hpp
+++ b/src/LocalDiscretization/moab/ElemEvaluator.hpp
@@ -88,7 +88,8 @@ namespace moab {
       int nv;
       EntityType tp = mb->type_from_handle(eh);
       const EntityHandle *connect;
-      ErrorCode rval = mb->get_connectivity(eh, connect, nv);
+      std::vector<EntityHandle> dum_vec;
+      ErrorCode rval = mb->get_connectivity(eh, connect, nv, false, &dum_vec);
       if (MB_SUCCESS != rval) return rval;
       
       return get_eval_set(tp, nv, eval_set);
@@ -208,7 +209,7 @@ namespace moab {
         * NOTE: this function should only be called after setting a valid MOAB instance on the evaluator
         * \param eh Entity handle whose type and #vertices are queried
         */
-      ErrorCode set_eval_set(EntityHandle eh);
+      ErrorCode set_eval_set(const EntityHandle eh);
       
         /** \brief Get the eval set for a given type entity */
       inline EvalSet get_eval_set(EntityType tp) {return evalSets[tp];}
@@ -319,7 +320,8 @@ namespace moab {
       entType = mbImpl->type_from_handle(ent);
       entDim = mbImpl->dimension_from_handle(ent);
 
-      ErrorCode rval = mbImpl->get_connectivity(ent, vertHandles, numVerts);
+      std::vector<EntityHandle> dum_vec;
+      ErrorCode rval = mbImpl->get_connectivity(ent, vertHandles, numVerts, false, &dum_vec);
       if (MB_SUCCESS != rval) return rval;
       rval = mbImpl->get_coords(vertHandles, numVerts, vertPos[0].array());
       if (MB_SUCCESS != rval) return rval;
@@ -479,7 +481,7 @@ namespace moab {
       return (*evalSets[entType].insideFcn)(params, entDim, tol);
     }
 
-    inline ErrorCode ElemEvaluator::set_eval_set(EntityHandle eh) 
+    inline ErrorCode ElemEvaluator::set_eval_set(const EntityHandle eh) 
     {
       EvalSet eset;
       ErrorCode rval = EvalSet::get_eval_set(mbImpl, eh, evalSets[mbImpl->type_from_handle(eh)]); 

diff --git a/src/Makefile.am b/src/Makefile.am
index e193dc3..94c256d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -159,6 +159,7 @@ nobase_libMOAB_la_include_HEADERS = \
   moab/CartVect.hpp \
   moab/Compiler.hpp \
   moab/Core.hpp \
+  moab/CpuTimer.hpp \
   moab/DualTool.hpp \
   moab/Error.hpp \
   moab/GeomTopoTool.hpp \

diff --git a/src/SpatialLocator.cpp b/src/SpatialLocator.cpp
index 8397ad7..a543dc9 100644
--- a/src/SpatialLocator.cpp
+++ b/src/SpatialLocator.cpp
@@ -98,7 +98,7 @@ namespace moab
           bool *is_ptr = (is_inside ? is_inside+i : &tmp_inside);      
           rval = elemEval->set_ent_handle(*rit); 
           if (MB_SUCCESS != rval) return rval;
-          rval = elemEval->reverse_eval(pos+i3, 0.0, params+i3, is_ptr);
+          rval = elemEval->reverse_eval(pos+i3, abs_eps, params+i3, is_ptr);
           if (MB_SUCCESS != rval) return rval;
           if (*is_ptr) {
             ents[i] = *rit;

diff --git a/src/io/NCHelperEuler.cpp b/src/io/NCHelperEuler.cpp
index a01d4b8..b621fa3 100644
--- a/src/io/NCHelperEuler.cpp
+++ b/src/io/NCHelperEuler.cpp
@@ -1,6 +1,6 @@
 #include "NCHelperEuler.hpp"
 #include "moab/ReadUtilIface.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 
 #include <cmath>
 #include <sstream>

diff --git a/src/io/NCHelperFV.cpp b/src/io/NCHelperFV.cpp
index 566b719..7cc4aef 100644
--- a/src/io/NCHelperFV.cpp
+++ b/src/io/NCHelperFV.cpp
@@ -1,6 +1,6 @@
 #include "NCHelperFV.hpp"
 #include "moab/ReadUtilIface.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 
 #include <cmath>
 #include <sstream>

diff --git a/src/io/NCHelperHOMME.cpp b/src/io/NCHelperHOMME.cpp
index 32faa58..57a5432 100644
--- a/src/io/NCHelperHOMME.cpp
+++ b/src/io/NCHelperHOMME.cpp
@@ -1,6 +1,6 @@
 #include "NCHelperHOMME.hpp"
 #include "moab/ReadUtilIface.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "moab/SpectralMeshTool.hpp"
 
 #include <cmath>

diff --git a/src/io/ReadABAQUS.cpp b/src/io/ReadABAQUS.cpp
index 1c44057..b3a37d0 100644
--- a/src/io/ReadABAQUS.cpp
+++ b/src/io/ReadABAQUS.cpp
@@ -36,7 +36,7 @@
 #include "moab/ReadUtilIface.hpp"
 #include "AffineXform.hpp"
 // #include "abaqus_order.h"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 
 namespace moab {
 

diff --git a/src/io/ReadCCMIO.cpp b/src/io/ReadCCMIO.cpp
index 3161425..ec53b6c 100644
--- a/src/io/ReadCCMIO.cpp
+++ b/src/io/ReadCCMIO.cpp
@@ -11,7 +11,7 @@
 #include "MBTagConventions.hpp"
 #include "Internals.hpp"
 #include "moab/ReadUtilIface.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "ReadCCMIO.hpp"
 #include "moab/MeshTopoUtil.hpp"
 

diff --git a/src/io/ReadCGM.cpp b/src/io/ReadCGM.cpp
index 02f748e..a610d4a 100644
--- a/src/io/ReadCGM.cpp
+++ b/src/io/ReadCGM.cpp
@@ -37,7 +37,7 @@
 #include "moab/Interface.hpp"
 #include "moab/Range.hpp"
 #include "MBTagConventions.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 
 #include "moab/GeomTopoTool.hpp"
 

diff --git a/src/io/ReadDamsel.cpp b/src/io/ReadDamsel.cpp
index 8d1bcfe..f02f0ea 100644
--- a/src/io/ReadDamsel.cpp
+++ b/src/io/ReadDamsel.cpp
@@ -13,7 +13,7 @@
 #include "moab/Range.hpp"
 #include "moab/Error.hpp"
 #include "moab/ReadUtilIface.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "MBTagConventions.hpp"
 #include "EntitySequence.hpp"
 #include "Internals.hpp"

diff --git a/src/io/ReadGCRM.cpp b/src/io/ReadGCRM.cpp
index 19d789e..0b86bd6 100644
--- a/src/io/ReadGCRM.cpp
+++ b/src/io/ReadGCRM.cpp
@@ -15,7 +15,7 @@
 #include "moab/ReaderIface.hpp"
 #include "moab/ReadUtilIface.hpp"
 #include "MBTagConventions.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 
 #define ERRORR(rval, str) \
     if (MB_SUCCESS != rval) {readMeshIface->report_error("%s", str); return rval;}

diff --git a/src/io/ReadHDF5.cpp b/src/io/ReadHDF5.cpp
index 5e90822..ec17ccd 100644
--- a/src/io/ReadHDF5.cpp
+++ b/src/io/ReadHDF5.cpp
@@ -38,7 +38,7 @@
 #include "MBTagConventions.hpp"
 #include "ReadHDF5.hpp"
 #include "moab/CN.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #ifdef HDF5_PARALLEL
 #  include <H5FDmpi.h>
 #  include <H5FDmpio.h>

diff --git a/src/io/ReadMCNP5.cpp b/src/io/ReadMCNP5.cpp
index c05ed41..b290f75 100644
--- a/src/io/ReadMCNP5.cpp
+++ b/src/io/ReadMCNP5.cpp
@@ -18,7 +18,7 @@
 #include "moab/ReadUtilIface.hpp"
 #include "Internals.hpp" // for MB_START_ID
 #include "moab/Range.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 
 #include <iostream>
 #include <sstream>

diff --git a/src/io/ReadNASTRAN.cpp b/src/io/ReadNASTRAN.cpp
index 6534417..47a8780 100644
--- a/src/io/ReadNASTRAN.cpp
+++ b/src/io/ReadNASTRAN.cpp
@@ -27,7 +27,7 @@
 #include "moab/ReadUtilIface.hpp"
 #include "Internals.hpp" // for MB_START_ID
 #include "moab/Range.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "FileTokenizer.hpp"
 #include "MBTagConventions.hpp"
 #include "moab/CN.hpp"

diff --git a/src/io/ReadNC.cpp b/src/io/ReadNC.cpp
index 514f724..c18ee96 100644
--- a/src/io/ReadNC.cpp
+++ b/src/io/ReadNC.cpp
@@ -16,7 +16,7 @@
 #include "moab/ReaderIface.hpp"
 #include "moab/ReadUtilIface.hpp"
 #include "MBTagConventions.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "moab/ScdInterface.hpp"
 #include "moab/SpectralMeshTool.hpp"
 

diff --git a/src/io/ReadNCDF.cpp b/src/io/ReadNCDF.cpp
index c1ffe69..3ed25d1 100644
--- a/src/io/ReadNCDF.cpp
+++ b/src/io/ReadNCDF.cpp
@@ -38,7 +38,7 @@
 #include "Internals.hpp"
 #include "moab/ReadUtilIface.hpp"
 #include "exodus_order.h"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "moab/AdaptiveKDTree.hpp"
 #include "moab/CartVect.hpp"
 

diff --git a/src/io/ReadSTL.cpp b/src/io/ReadSTL.cpp
index 4ba085d..59bd80b 100644
--- a/src/io/ReadSTL.cpp
+++ b/src/io/ReadSTL.cpp
@@ -25,7 +25,7 @@
 #include "moab/Interface.hpp"
 #include "moab/ReadUtilIface.hpp"
 #include "moab/Range.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "SysUtil.hpp"
 
 #include <errno.h>

diff --git a/src/io/ReadSmf.cpp b/src/io/ReadSmf.cpp
index 0970d71..eac232e 100644
--- a/src/io/ReadSmf.cpp
+++ b/src/io/ReadSmf.cpp
@@ -28,7 +28,7 @@
 #include "Internals.hpp"
 #include "moab/Interface.hpp"
 #include "moab/ReadUtilIface.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "AffineXform.hpp"
 
 static inline int streq(const char *a,const char *b) { return strcmp(a,b)==0; }

diff --git a/src/io/ReadTemplate.cpp b/src/io/ReadTemplate.cpp
index 309a71e..97f70ce 100644
--- a/src/io/ReadTemplate.cpp
+++ b/src/io/ReadTemplate.cpp
@@ -8,7 +8,7 @@
 #include "moab/Interface.hpp"
 #include "moab/ReadUtilIface.hpp"
 #include "moab/Range.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 
 #include <cstdio>
 #include <assert.h>

diff --git a/src/io/ReadTetGen.cpp b/src/io/ReadTetGen.cpp
index 72197fb..1d6609a 100644
--- a/src/io/ReadTetGen.cpp
+++ b/src/io/ReadTetGen.cpp
@@ -2,7 +2,7 @@
 #include "moab/Interface.hpp"
 #include "moab/Range.hpp"
 #include "moab/ReadUtilIface.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "MBTagConventions.hpp"
 #include <iostream>
 #include <fstream>

diff --git a/src/io/ReadVtk.cpp b/src/io/ReadVtk.cpp
index ac3b9e4..2936a85 100644
--- a/src/io/ReadVtk.cpp
+++ b/src/io/ReadVtk.cpp
@@ -28,7 +28,7 @@
 #include "Internals.hpp"
 #include "moab/Interface.hpp"
 #include "moab/ReadUtilIface.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "FileTokenizer.hpp"
 #include "VtkUtil.hpp"
 

diff --git a/src/io/Tqdcfr.cpp b/src/io/Tqdcfr.cpp
index 833b15b..08c5a0c 100644
--- a/src/io/Tqdcfr.cpp
+++ b/src/io/Tqdcfr.cpp
@@ -16,7 +16,7 @@
 #include "Tqdcfr.hpp"
 #include "moab/Core.hpp"
 #include "moab/Range.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include <iostream>
 #include <string>
 

diff --git a/src/io/WriteDamsel.hpp b/src/io/WriteDamsel.hpp
index 8902f08..fff9e8b 100644
--- a/src/io/WriteDamsel.hpp
+++ b/src/io/WriteDamsel.hpp
@@ -26,7 +26,7 @@
 #include "moab/Range.hpp"
 #include "moab/WriterIface.hpp"
 #include "RangeSeqIntersectIter.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "DamselUtil.hpp"
 
 #include "damsel.h"

diff --git a/src/io/WriteGmsh.cpp b/src/io/WriteGmsh.cpp
index aac3d38..7d4e2f7 100644
--- a/src/io/WriteGmsh.cpp
+++ b/src/io/WriteGmsh.cpp
@@ -5,7 +5,7 @@
 #include "moab/Interface.hpp"
 #include "moab/Range.hpp"
 #include "moab/WriteUtilIface.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "GmshUtil.hpp"
 
 #include <fstream>

diff --git a/src/io/WriteHDF5.cpp b/src/io/WriteHDF5.cpp
index 839c455..337cb96 100644
--- a/src/io/WriteHDF5.cpp
+++ b/src/io/WriteHDF5.cpp
@@ -48,17 +48,12 @@
 #include "Internals.hpp"
 #include "MBTagConventions.hpp"
 #include "moab/CN.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "moab/Version.h"
+#include "moab/CpuTimer.hpp"
 #include "IODebugTrack.hpp"
 #include "mhdf.h"
 
-#ifdef USE_MPI
-#define RUNTIME MPI_Wtime()
-#else
-#define RUNTIME (clock()/(double)CLOCKS_PER_SEC)
-#endif
-
 /* Access HDF5 file handle for debugging
 #include <H5Fpublic.h>
 struct file { uint32_t magic; hid_t handle; };
@@ -100,15 +95,6 @@ struct file { uint32_t magic; hid_t handle; };
 
 namespace moab {
 
-class CpuTimer {
-private:
-  double atBirth, atLast;
-public:
-  CpuTimer() : atBirth(RUNTIME), atLast(atBirth) {}
-  double since_birth() { return (atLast = RUNTIME) - atBirth; };
-  double elapsed() { double tmp = atLast; return (atLast = RUNTIME) - tmp; }
-};
-
 template <typename T> inline 
 void VALGRIND_MAKE_VEC_UNDEFINED( std::vector<T>& v ) {
     VALGRIND_MAKE_MEM_UNDEFINED( &v[0], v.size() * sizeof(T) );
@@ -601,7 +587,7 @@ ErrorCode WriteHDF5::write_file_impl( const char* filename,
   topState.end(result);
   CHK_MB_ERR_0(result);
   
-  times[GATHER_TIME] = timer.elapsed();
+  times[GATHER_TIME] = timer.time_elapsed();
   
   //if (nodeSet.range.size() == 0)
   //  return error(MB_ENTITY_NOT_FOUND);
@@ -650,7 +636,7 @@ ErrorCode WriteHDF5::write_file_impl( const char* filename,
   if (MB_SUCCESS != result)
     return error(result);
 
-  times[CREATE_TIME] = timer.elapsed();
+  times[CREATE_TIME] = timer.time_elapsed();
 
   dbgOut.tprint(1,"Writing Nodes.\n");
     // Write node coordinates
@@ -662,7 +648,7 @@ ErrorCode WriteHDF5::write_file_impl( const char* filename,
       return error(result);
   }
 
-  times[COORD_TIME] = timer.elapsed();
+  times[COORD_TIME] = timer.time_elapsed();
 
   dbgOut.tprint(1,"Writing connectivity.\n");
   
@@ -674,7 +660,7 @@ ErrorCode WriteHDF5::write_file_impl( const char* filename,
     if (MB_SUCCESS != result)
       return error(result);
   }
-  times[CONN_TIME] = timer.elapsed();
+  times[CONN_TIME] = timer.time_elapsed();
 
   dbgOut.tprint(1,"Writing sets.\n");
   
@@ -684,7 +670,7 @@ ErrorCode WriteHDF5::write_file_impl( const char* filename,
     return error(result);
   debug_barrier();
   
-  times[SET_TIME] = timer.elapsed();
+  times[SET_TIME] = timer.time_elapsed();
   dbgOut.tprint(1,"Writing adjacencies.\n");
   
     // Write adjacencies
@@ -701,7 +687,7 @@ ErrorCode WriteHDF5::write_file_impl( const char* filename,
     if (MB_SUCCESS != result)
       return error(result);
   }
-  times[ADJ_TIME] = timer.elapsed();
+  times[ADJ_TIME] = timer.time_elapsed();
 
   dbgOut.tprint(1,"Writing tags.\n");
   
@@ -716,9 +702,9 @@ ErrorCode WriteHDF5::write_file_impl( const char* filename,
     if (MB_SUCCESS != result)
       return error(result);
   }
-  times[TAG_TIME] = timer.elapsed();
+  times[TAG_TIME] = timer.time_elapsed();
   
-  times[TOTAL_TIME] = timer.since_birth();
+  times[TOTAL_TIME] = timer.time_since_birth();
 
   if (cputime) {
     print_times( times );
@@ -1374,7 +1360,7 @@ ErrorCode WriteHDF5::write_sets( double* times )
     mhdf_closeData( filePtr, table, &status );
     CHK_MHDF_ERR_0(status);
    
-    times[SET_PARENT] = timer.elapsed();
+    times[SET_PARENT] = timer.time_elapsed();
     track.all_reduce();
   }
   
@@ -1393,7 +1379,7 @@ ErrorCode WriteHDF5::write_sets( double* times )
     mhdf_closeData( filePtr, table, &status );
     CHK_MHDF_ERR_0(status);
    
-    times[SET_CHILD] = timer.elapsed();
+    times[SET_CHILD] = timer.time_elapsed();
     track.all_reduce();
   }
   
@@ -1415,7 +1401,7 @@ ErrorCode WriteHDF5::write_sets( double* times )
     mhdf_closeData( filePtr, table, &status );
     CHK_MHDF_ERR_0(status);
    
-    times[SET_CONTENT] = timer.elapsed();
+    times[SET_CONTENT] = timer.time_elapsed();
     track.all_reduce();
   }
   assert( ranged_sets.size() + null_stripped_sets.size() == set_sizes.size() );
@@ -1544,7 +1530,7 @@ ErrorCode WriteHDF5::write_sets( double* times )
   mhdf_closeData( filePtr, table, &status );
   CHK_MHDF_ERR_0(status);
 
-  times[SET_META] = timer.elapsed();
+  times[SET_META] = timer.time_elapsed();
   track_meta.all_reduce();
 
   return MB_SUCCESS;
@@ -1881,7 +1867,7 @@ ErrorCode WriteHDF5::write_tag( const TagDesc& tag_data,
   if (array_len == MB_VARIABLE_LENGTH && tag_data.write_sparse) {
     dbgOut.printf( 2, "Writing sparse data for var-len tag: \"%s\"\n", name.c_str() );
     rval = write_var_len_tag( tag_data, name, moab_type, hdf5_type, elem_size );
-    times[VARLEN_TAG_TIME] += timer.elapsed();
+    times[VARLEN_TAG_TIME] += timer.time_elapsed();
   }
   else {
     int data_len = elem_size;
@@ -1890,7 +1876,7 @@ ErrorCode WriteHDF5::write_tag( const TagDesc& tag_data,
     if (tag_data.write_sparse) {
       dbgOut.printf( 2, "Writing sparse data for tag: \"%s\"\n", name.c_str() );
       rval = write_sparse_tag( tag_data, name, moab_type, hdf5_type, data_len );
-      times[SPARSE_TAG_TIME] += timer.elapsed();
+      times[SPARSE_TAG_TIME] += timer.time_elapsed();
     }
     for (size_t i = 0; MB_SUCCESS == rval && i < tag_data.dense_list.size(); ++i) {
       const ExportSet* set = find( tag_data.dense_list[i] );
@@ -1901,7 +1887,7 @@ ErrorCode WriteHDF5::write_tag( const TagDesc& tag_data,
       rval = write_dense_tag( tag_data, *set, name, moab_type, hdf5_type, data_len );
       subState.end(rval);
     }
-    times[DENSE_TAG_TIME] += timer.elapsed();
+    times[DENSE_TAG_TIME] += timer.time_elapsed();
   }
  
   H5Tclose( hdf5_type );

diff --git a/src/io/WriteSTL.cpp b/src/io/WriteSTL.cpp
index 62644a6..45718d8 100644
--- a/src/io/WriteSTL.cpp
+++ b/src/io/WriteSTL.cpp
@@ -25,7 +25,7 @@
 #include "moab/Interface.hpp"
 #include "moab/Range.hpp"
 #include "moab/WriteUtilIface.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "SysUtil.hpp"
 
 #include <stdio.h>

diff --git a/src/io/WriteSmf.cpp b/src/io/WriteSmf.cpp
index 0a09b8b..9d7f5f0 100644
--- a/src/io/WriteSmf.cpp
+++ b/src/io/WriteSmf.cpp
@@ -40,7 +40,7 @@
 #include "MBTagConventions.hpp"
 #include "moab/WriteUtilIface.hpp"
 #include "Internals.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "moab/Version.h"
 
 namespace moab {

diff --git a/src/io/WriteVtk.cpp b/src/io/WriteVtk.cpp
index 03e95e4..bfda520 100644
--- a/src/io/WriteVtk.cpp
+++ b/src/io/WriteVtk.cpp
@@ -41,7 +41,7 @@
 #include "MBTagConventions.hpp"
 #include "moab/WriteUtilIface.hpp"
 #include "Internals.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "moab/Version.h"
 
 #define INS_ID(stringvar, prefix, id) \

diff --git a/src/moab/CpuTimer.hpp b/src/moab/CpuTimer.hpp
new file mode 100644
index 0000000..cdda903
--- /dev/null
+++ b/src/moab/CpuTimer.hpp
@@ -0,0 +1,63 @@
+#ifndef CPUTIMER_HPP
+#define CPUTIMER_HPP
+
+#ifdef USE_MPI
+#  include "moab_mpi.h"
+#else
+#  include <sys/resource.h>
+#endif
+
+namespace moab 
+{
+    
+class CpuTimer {
+private:
+  double tAtBirth, tAtLast;
+  double mAtBirth, mAtLast;
+  long rssAtBirth, rssAtLast;
+
+  double runtime();
+  long runmem();
+  
+public:
+  CpuTimer() : tAtBirth(runtime()), tAtLast(tAtBirth) {}
+  double time_since_birth() { return (tAtLast = runtime()) - tAtBirth; };
+  double time_elapsed() { double tmp = tAtLast; return (tAtLast = runtime()) - tmp; }
+  long mem_since_birth() {return (mAtLast=runmem()) - mAtBirth;}
+  long mem_elapsed() {long tmp = mAtLast; return (mAtLast=runmem()) - tmp;}
+};
+
+    inline double CpuTimer::runtime() 
+    {
+#if defined(_MSC_VER) || defined(__MINGW32__)
+      return (double)clock() / CLOCKS_PER_SEC;
+#elif defined(USE_MPI)
+      return MPI_Wtime();
+#else      
+      struct rusage r_usage;
+      getrusage(RUSAGE_SELF, &r_usage);
+      double utime = (double)r_usage.ru_utime.tv_sec +
+          ((double)r_usage.ru_utime.tv_usec/1.e6);
+      double stime = (double)r_usage.ru_stime.tv_sec +
+          ((double)r_usage.ru_stime.tv_usec/1.e6);
+      return utime + stime;
+#endif
+    }
+
+    inline long CpuTimer::runmem() 
+    {
+#if defined(_MSC_VER) || defined(__MINGW32__)
+      return 0;
+#elif defined(USE_MPI)
+      return 0;
+#else
+      struct rusage r_usage;
+      getrusage(RUSAGE_SELF, &r_usage);
+      mAtLast = r_usage.ru_maxrss;
+      return mAtLast;
+#endif
+    }
+
+}
+
+#endif

diff --git a/src/moab/Tree.hpp b/src/moab/Tree.hpp
index da2099a..c2a117c 100644
--- a/src/moab/Tree.hpp
+++ b/src/moab/Tree.hpp
@@ -170,7 +170,11 @@ namespace moab {
         //! get/set the ElemEvaluator
       inline void set_eval(ElemEvaluator *eval) {myEval = eval;}
       
-            
+        /** \brief Parse options for this tree, including common options for all trees
+         * \param opts Options
+         */
+      virtual ErrorCode parse_options(FileOptions &opts) = 0;
+
   protected:
 
         /** \brief Parse options common to all trees

diff --git a/src/moab/TreeStats.hpp b/src/moab/TreeStats.hpp
index 738aae9..be619a5 100644
--- a/src/moab/TreeStats.hpp
+++ b/src/moab/TreeStats.hpp
@@ -40,9 +40,15 @@ namespace moab
         //! reset all counters
       void reset();
               
-        //! print the contents of this structure to given stream
+        //! print the contents of this structure
       void print() const ;
 
+        //! output the contents of this structure on a single line
+      void output() const ;
+
+        // times
+      double initTime;
+
         // tree stats that depend only on structure (not traversal)
       unsigned int maxDepth;
       unsigned int numNodes;
@@ -90,6 +96,8 @@ namespace moab
 
     inline void TreeStats::reset()
     {
+      initTime = 0.0;
+      
       maxDepth = 0;
       numNodes = 0;
       numLeaves = 0;
@@ -106,11 +114,19 @@ namespace moab
     }
     
     inline void TreeStats::print() const {
+      std::cout << "Tree initialization time = " << initTime << " seconds" << std::endl;
+      
       std::cout << "NodesVisited      = " << nodesVisited << std::endl;
       std::cout << "LeavesVisited     = " << leavesVisited << std::endl;
       std::cout << "Num Traversals    = " << numTraversals << std::endl;
       std::cout << "Leaf Object Tests = " << leafObjectTests << std::endl;
     }
+
+    inline void TreeStats::output() const 
+    {
+      std::cout << initTime << " " << nodesVisited << " " << leavesVisited << " " << numTraversals << " " << leafObjectTests
+                << " # initTime, nodesVisited, leavesVisited, numTraversals, leafObjectTests" << std::endl;
+    }
 }
 
     

diff --git a/src/parallel/ReadParallel.cpp b/src/parallel/ReadParallel.cpp
index 96492fc..fe4ed55 100644
--- a/src/parallel/ReadParallel.cpp
+++ b/src/parallel/ReadParallel.cpp
@@ -1,7 +1,7 @@
 #include "ReadParallel.hpp"
 #include "moab/Core.hpp"
 #include "moab/ProcConfig.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "moab/Error.hpp"
 #include "moab/ReaderWriterSet.hpp"
 #include "moab/ReadUtilIface.hpp"

diff --git a/src/parallel/WriteHDF5Parallel.cpp b/src/parallel/WriteHDF5Parallel.cpp
index 4fbca9e..20a36a3 100644
--- a/src/parallel/WriteHDF5Parallel.cpp
+++ b/src/parallel/WriteHDF5Parallel.cpp
@@ -40,7 +40,7 @@
 #include "moab/Range.hpp"
 
 #include "IODebugTrack.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 
 namespace {
   template<bool Condition> struct STATIC_ASSERTION;

diff --git a/test/h5file/h5partial.cpp b/test/h5file/h5partial.cpp
index 7df5203..17abc06 100644
--- a/test/h5file/h5partial.cpp
+++ b/test/h5file/h5partial.cpp
@@ -3,7 +3,7 @@
 #include "TestRunner.hpp"
 #include "ReadHDF5.hpp"
 #include "MBTagConventions.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 
 #ifdef USE_MPI
 #include "moab_mpi.h"

diff --git a/test/h5file/h5portable.cpp b/test/h5file/h5portable.cpp
index 7a4fe89..42dfd05 100644
--- a/test/h5file/h5portable.cpp
+++ b/test/h5file/h5portable.cpp
@@ -11,7 +11,7 @@
 #include "TestRunner.hpp"
 #include "ReadHDF5.hpp"
 #include "MBTagConventions.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include <vector>
 #include <stdlib.h>
 #include <iostream>

diff --git a/test/h5file/h5regression.cpp b/test/h5file/h5regression.cpp
index eed72c3..584bfd6 100644
--- a/test/h5file/h5regression.cpp
+++ b/test/h5file/h5regression.cpp
@@ -3,7 +3,7 @@
 #include "moab/Range.hpp"
 #include "moab/ReadUtilIface.hpp"
 #include "WriteHDF5.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 
 #ifdef USE_MPI
 #include "moab_mpi.h"

diff --git a/test/io/ccmio_test.cpp b/test/io/ccmio_test.cpp
index 755554b..3dc298d 100644
--- a/test/io/ccmio_test.cpp
+++ b/test/io/ccmio_test.cpp
@@ -2,7 +2,7 @@
 #include "moab/Core.hpp"
 #define IS_BUILDING_MB
 #include "moab/Range.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 
 using namespace moab;
 

diff --git a/test/io/exodus_test.cc b/test/io/exodus_test.cc
index 9707431..c5d8786 100644
--- a/test/io/exodus_test.cc
+++ b/test/io/exodus_test.cc
@@ -4,7 +4,7 @@
 #include "moab/CN.hpp"
 #include "moab/Range.hpp"
 #include "ReadNCDF.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #define IS_BUILDING_MB
 #include "ExoIIUtil.hpp"
 #include <math.h>

diff --git a/test/parallel/parallel_unit_tests.cpp b/test/parallel/parallel_unit_tests.cpp
index 7d47a4c..ad24d5b 100644
--- a/test/parallel/parallel_unit_tests.cpp
+++ b/test/parallel/parallel_unit_tests.cpp
@@ -1,7 +1,7 @@
 #include "moab/ParallelComm.hpp"
 #include "MBParallelConventions.h"
 #include "ReadParallel.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "MBTagConventions.hpp"
 #include "moab/Core.hpp"
 #include "moab_mpi.h"

diff --git a/test/parallel/pcomm_serial.cpp b/test/parallel/pcomm_serial.cpp
index dd6752e..32c30e7 100644
--- a/test/parallel/pcomm_serial.cpp
+++ b/test/parallel/pcomm_serial.cpp
@@ -2,7 +2,7 @@
 #include "MBParallelConventions.h"
 #include "MBTagConventions.hpp"
 #include "moab/Core.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "ReadParallel.hpp"
 #include "TestUtil.hpp"
 #include <vector>

diff --git a/test/parallel/pcomm_unit.cpp b/test/parallel/pcomm_unit.cpp
index 5e1c5d3..f2698dd 100644
--- a/test/parallel/pcomm_unit.cpp
+++ b/test/parallel/pcomm_unit.cpp
@@ -4,7 +4,7 @@
 #include "moab/Core.hpp"
 #include "moab/MeshTopoUtil.hpp"
 #include "ReadParallel.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "TestUtil.hpp"
 #include <algorithm>
 #include <vector>

diff --git a/test/parallel/uber_parallel_test.cpp b/test/parallel/uber_parallel_test.cpp
index 665d620..d995342 100644
--- a/test/parallel/uber_parallel_test.cpp
+++ b/test/parallel/uber_parallel_test.cpp
@@ -1,7 +1,7 @@
 #include "moab/ParallelComm.hpp"
 #include "MBParallelConventions.h"
 #include "ReadParallel.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "MBTagConventions.hpp"
 #include "moab/Core.hpp"
 #include "moab_mpi.h"

diff --git a/test/perf/Makefile.am b/test/perf/Makefile.am
index 07b90a0..f946f94 100644
--- a/test/perf/Makefile.am
+++ b/test/perf/Makefile.am
@@ -1,3 +1,4 @@
+SUBDIRS = point_location
 
 AM_CPPFLAGS += -I$(top_srcdir)/src \
                -I$(top_srcdir)/src/io/mhdf/include \

diff --git a/test/perf/point_location/Makefile.am b/test/perf/point_location/Makefile.am
index f34f41d..2d59114 100644
--- a/test/perf/point_location/Makefile.am
+++ b/test/perf/point_location/Makefile.am
@@ -6,13 +6,20 @@ AM_CPPFLAGS += -I$(top_srcdir)/src \
                -I$(top_srcdir)/src/LocalDiscretization/ \
                -I$(top_srcdir)/tools/mbcoupler \
                -I$(top_srcdir)/src/moab/point_locator/lotte \
+               -I$(top_srcdir)/src/LocalDiscretization/moab/ \
                -DIS_BUILDING_MB
-            
+
+# might need parallel here because of timer
+if PARALLEL
+  AM_CPPFLAGS += -I$(top_srcdir)/src/parallel
+endif
+
 LDADD = $(top_builddir)/src/libMOAB.la $(top_builddir)/tools/mbcoupler/libmbcoupler.la
 
-check_PROGRAMS = 
-noinst_PROGRAMS = point_location elem_eval_time
+check_PROGRAMS = point_location elem_eval_time tree_searching_perf sploc_searching_perf
+noinst_PROGRAMS =
 
 point_location_SOURCES = point_location.cpp
 elem_eval_time_SOURCES = elem_eval_time.cpp
-
+tree_searching_perf_SOURCES = tree_searching_perf.cpp
+sploc_searching_perf_SOURCES = sploc_searching_perf.cpp

diff --git a/test/perf/point_location/point_location.cpp b/test/perf/point_location/point_location.cpp
index 92ccc83..df4132e 100644
--- a/test/perf/point_location/point_location.cpp
+++ b/test/perf/point_location/point_location.cpp
@@ -290,7 +290,7 @@ void do_kdtree_test( Interface& mb, int tree_depth, int elem_per_leaf,
   int len;
   for (long i = 0; i < num_test; ++i) {
     const size_t idx = (size_t)i % points.size();
-    rval = tool.point_search( points[idx].array(), leaf, NULL, &root ); CHK(rval);
+    rval = tool.point_search( points[idx].array(), leaf, 0.0, NULL, &root ); CHK(rval);
     hexes.clear();
     rval = mb.get_entities_by_handle( leaf, hexes ); CHK(rval);
     for (j = hexes.begin(); j != hexes.end(); ++j) {

diff --git a/test/perf/point_location/sploc_searching_perf.cpp b/test/perf/point_location/sploc_searching_perf.cpp
new file mode 100644
index 0000000..bf09a8e
--- /dev/null
+++ b/test/perf/point_location/sploc_searching_perf.cpp
@@ -0,0 +1,194 @@
+#include "moab/Core.hpp"
+#include "moab/SpatialLocator.hpp"
+#include "moab/Tree.hpp"
+#include "moab/HomXform.hpp"
+#include "moab/ScdInterface.hpp"
+#include "moab/CartVect.hpp"
+#include "moab/AdaptiveKDTree.hpp"
+#include "moab/BVHTree.hpp"
+#include "moab/ProgOptions.hpp"
+#include "moab/CpuTimer.hpp"
+#include "moab/ElemEvaluator.hpp"
+
+#ifdef USE_MPI
+#include "moab_mpi.h"
+#endif
+
+#include <cstdlib>
+#include <sstream>
+
+using namespace moab;
+
+ErrorCode test_locator(SpatialLocator &sl, int npoints, double rtol, double &cpu_time, double &percent_outside);
+ErrorCode create_hex_mesh(Interface &mb, Range &elems, int n, int dim);
+
+int main(int argc, char **argv)
+{
+#ifdef USE_MPI
+  int fail = MPI_Init(&argc, &argv);
+  if (fail) return fail;
+#else
+  // silence the warning of parameters not used, in serial; there should be a smarter way :(
+  argv[0]=argv[argc-argc];
+#endif
+
+  int npoints = 100, dim = 3;
+  int dints = 1, dleafs = 1, ddeps = 1;
+  bool eval = false;
+  double rtol = 1.0e-10;
+  
+  ProgOptions po("tree_searching_perf options" );
+  po.addOpt<void>( ",e", "Use ElemEvaluator in tree search", &eval);
+  po.addOpt<int>( "ints,i", "Number of doublings of intervals on each side of scd mesh", &dints);
+  po.addOpt<int>( "leaf,l", "Number of doublings of maximum number of elements per leaf", &dleafs);
+  po.addOpt<int>( "max_depth,m", "Number of 5-intervals on maximum depth of tree", &ddeps);
+  po.addOpt<int>( "npoints,n", "Number of query points", &npoints);
+  po.addOpt<double>( "tol,t", "Relative tolerance of point search", &rtol);
+//  po.addOpt<void>( "print,p", "Print tree details", &print_tree);
+  po.parseCommandLine(argc, argv);
+
+  std::vector<int> ints, deps, leafs;
+  ints.push_back(10);
+  for (int i = 1; i < dints; i++) ints.push_back(2*ints[i-1]);
+  deps.push_back(30);
+  for (int i = 1; i < ddeps; i++) deps.push_back(deps[i-1]-5);
+  leafs.push_back(6);
+  for (int i = 1; i < dleafs; i++) leafs.push_back(2*leafs[i-1]);
+
+  ErrorCode rval = MB_SUCCESS;
+  std::cout << "Tree_type" << " "
+            << "Elems_per_leaf" << " "
+            << "Tree_depth" << " "
+            << "Ints_per_side" << " "
+            << "N_elements" << " "
+            << "search_time" << " "
+            << "perc_outside" << " "
+            << "initTime" << " "
+            << "nodesVisited" << " "
+            << "leavesVisited" << " "
+            << "numTraversals" << " "
+            << "leafObjectTests" << std::endl;
+
+// outermost iteration: # elements
+  for (std::vector<int>::iterator int_it = ints.begin(); int_it != ints.end(); int_it++) {
+    Core mb;
+    Range elems;
+    rval = create_hex_mesh(mb, elems, *int_it, 3);
+    if (MB_SUCCESS != rval) return rval;
+    
+      // iteration: tree depth
+    for (std::vector<int>::iterator dep_it = deps.begin(); dep_it != deps.end(); dep_it++) {
+  
+        // iteration: tree max elems/leaf
+      for (std::vector<int>::iterator leafs_it = leafs.begin(); leafs_it != leafs.end(); leafs_it++) {
+  
+          // iteration: tree type
+        for (int tree_tp = 0; tree_tp < 2; tree_tp++) {
+            // create tree
+          Tree *tree;
+          if (0 == tree_tp)
+            tree = new BVHTree(&mb);
+          else
+            tree = new AdaptiveKDTree(&mb);
+
+          ElemEvaluator *eeval = NULL;
+          if (eval) {
+              // create an element evaluator
+            eeval = new ElemEvaluator(&mb);
+            rval = eeval->set_eval_set(*elems.begin());
+            if (MB_SUCCESS != rval) return rval;
+          }
+          
+          std::ostringstream opts;
+          opts << "MAX_DEPTH=" << *dep_it << ";MAX_PER_LEAF=" << *leafs_it;
+          FileOptions fo(opts.str().c_str());
+          rval = tree->parse_options(fo);
+          SpatialLocator sl(&mb, elems, tree, eeval);
+
+            // call evaluation
+          double cpu_time, perc_outside;
+          rval = test_locator(sl, npoints, rtol, cpu_time, perc_outside);
+          if (MB_SUCCESS != rval) return rval;
+
+          std::cout << (tree_tp == 0 ? "BVH" : "KD") << " "
+                    << *leafs_it << " "
+                    << *dep_it << " "
+                    << *int_it << " "
+                    << (*int_it)*(*int_it)*(dim == 3 ? *int_it : 1) << " "
+                    << cpu_time << " "
+                    << perc_outside << " ";
+
+          tree->tree_stats().output();
+
+          if (eeval) delete eeval;
+
+        } // tree_tp
+
+      } // max elems/leaf
+
+    } // max depth
+
+  } // # elements
+
+  
+#ifdef USE_MPI
+  fail = MPI_Finalize();
+  if (fail) return fail;
+#endif
+
+  return 0;
+}
+
+ErrorCode test_locator(SpatialLocator &sl, int npoints, double rtol, double &cpu_time, double &percent_outside) 
+{
+  BoundBox box;
+  ErrorCode rval = sl.get_bounding_box(box);
+  if (MB_SUCCESS != rval) return rval;
+  CartVect box_del = box.bMax - box.bMin;
+
+  std::vector<CartVect> test_pts(npoints), test_res(npoints);
+  std::vector<EntityHandle> ents(npoints);
+  bool *is_in = new bool[npoints];
+
+  double denom = 1.0 / (double)RAND_MAX;
+  for (int i = 0; i < npoints; i++) {    
+      // generate a small number of random point to test
+    double rx = (double)rand() * denom, ry = (double)rand() * denom, rz = (double)rand() * denom;
+    test_pts[i] = box.bMin + CartVect(rx*box_del[0], ry*box_del[1], rz*box_del[2]);
+  }
+  
+  CpuTimer ct;
+  
+    // call spatial locator to locate points
+  rval = sl.locate_points(test_pts[0].array(), npoints, &ents[0], test_res[0].array(), rtol, 0.0, &is_in[0]);
+  if (MB_SUCCESS != rval) return rval;
+
+  cpu_time = ct.time_elapsed();
+
+  int num_out = std::count(is_in, is_in+npoints, false);
+  percent_outside = ((double)num_out)/npoints;
+  delete [] is_in;
+  
+  return rval;
+}
+
+ErrorCode create_hex_mesh(Interface &mb, Range &elems, int n, int dim) 
+{
+  ScdInterface *scdi;
+  ErrorCode rval = mb.query_interface(scdi);
+  if (MB_SUCCESS != rval) return rval;
+  
+  HomCoord high(n-1, -1, -1);
+  if (dim > 1) high[1] = n-1;
+  if (dim > 2) high[2] = n-1;
+  ScdBox *new_box;
+  rval = scdi->construct_box(HomCoord(0, 0, 0), high, NULL, 0, new_box);
+  if (MB_SUCCESS != rval) return rval;
+  rval = mb.release_interface(scdi);
+  if (MB_SUCCESS != rval) return rval;
+
+  rval = mb.get_entities_by_dimension(0, dim, elems);
+  if (MB_SUCCESS != rval) return rval;
+
+  return rval;
+}

diff --git a/test/perf/point_location/tree_searching_perf.cpp b/test/perf/point_location/tree_searching_perf.cpp
new file mode 100644
index 0000000..6d1badb
--- /dev/null
+++ b/test/perf/point_location/tree_searching_perf.cpp
@@ -0,0 +1,179 @@
+#include "moab/Core.hpp"
+#include "moab/SpatialLocator.hpp"
+#include "moab/Tree.hpp"
+#include "moab/HomXform.hpp"
+#include "moab/ScdInterface.hpp"
+#include "moab/CartVect.hpp"
+#include "moab/AdaptiveKDTree.hpp"
+#include "moab/BVHTree.hpp"
+#include "moab/ProgOptions.hpp"
+#include "moab/CpuTimer.hpp"
+
+#ifdef USE_MPI
+#include "moab_mpi.h"
+#endif
+
+#include <cstdlib>
+#include <sstream>
+
+using namespace moab;
+
+ErrorCode test_locator(SpatialLocator &sl, int npoints, double &cpu_time, double &percent_outside);
+ErrorCode create_hex_mesh(Interface &mb, Range &elems, int n, int dim);
+
+int main(int argc, char **argv)
+{
+#ifdef USE_MPI
+  int fail = MPI_Init(&argc, &argv);
+  if (fail) return fail;
+#else
+  // silence the warning of parameters not used, in serial; there should be a smarter way :(
+  argv[0]=argv[argc-argc];
+#endif
+
+  int npoints = 100, dim = 3;
+  int dints = 1, dleafs = 1, ddeps = 1;
+  
+  ProgOptions po("tree_searching_perf options" );
+  po.addOpt<int>( "ints,i", "Number of doublings of intervals on each side of scd mesh", &dints);
+  po.addOpt<int>( "leaf,l", "Number of doublings of maximum number of elements per leaf", &dleafs);
+  po.addOpt<int>( "max_depth,m", "Number of 5-intervals on maximum depth of tree", &ddeps);
+  po.addOpt<int>( "npoints,n", "Number of query points", &npoints);
+//  po.addOpt<void>( "print,p", "Print tree details", &print_tree);
+  po.parseCommandLine(argc, argv);
+
+  std::vector<int> ints, deps, leafs;
+  ints.push_back(10);
+  for (int i = 1; i < dints; i++) ints.push_back(2*ints[i-1]);
+  deps.push_back(30);
+  for (int i = 1; i < ddeps; i++) deps.push_back(deps[i-1]-5);
+  leafs.push_back(6);
+  for (int i = 1; i < dleafs; i++) leafs.push_back(2*leafs[i-1]);
+
+  ErrorCode rval = MB_SUCCESS;
+  std::cout << "Tree_type" << " "
+            << "Elems_per_leaf" << " "
+            << "Tree_depth" << " "
+            << "Ints_per_side" << " "
+            << "N_elements" << " "
+            << "search_time" << " "
+            << "perc_outside" << " "
+            << "initTime" << " "
+            << "nodesVisited" << " "
+            << "leavesVisited" << " "
+            << "numTraversals" << " "
+            << "leafObjectTests" << std::endl;
+
+// outermost iteration: # elements
+  for (std::vector<int>::iterator int_it = ints.begin(); int_it != ints.end(); int_it++) {
+    Core mb;
+    Range elems;
+    rval = create_hex_mesh(mb, elems, *int_it, 3);
+    if (MB_SUCCESS != rval) return rval;
+    
+      // iteration: tree depth
+    for (std::vector<int>::iterator dep_it = deps.begin(); dep_it != deps.end(); dep_it++) {
+  
+        // iteration: tree max elems/leaf
+      for (std::vector<int>::iterator leafs_it = leafs.begin(); leafs_it != leafs.end(); leafs_it++) {
+  
+          // iteration: tree type
+        for (int tree_tp = 0; tree_tp < 2; tree_tp++) {
+            // create tree
+          Tree *tree;
+          if (0 == tree_tp)
+            tree = new BVHTree(&mb);
+          else
+            tree = new AdaptiveKDTree(&mb);
+
+          std::ostringstream opts;
+          opts << "MAX_DEPTH=" << *dep_it << ";MAX_PER_LEAF=" << *leafs_it;
+          FileOptions fo(opts.str().c_str());
+          rval = tree->parse_options(fo);
+          SpatialLocator sl(&mb, elems, tree);
+
+            // call evaluation
+          double cpu_time, perc_outside;
+          rval = test_locator(sl, npoints, cpu_time, perc_outside);
+          if (MB_SUCCESS != rval) return rval;
+
+          std::cout << (tree_tp == 0 ? "BVH" : "KD") << " "
+                    << *leafs_it << " "
+                    << *dep_it << " "
+                    << *int_it << " "
+                    << (*int_it)*(*int_it)*(dim == 3 ? *int_it : 1) << " "
+                    << cpu_time << " "
+                    << perc_outside << " ";
+
+          tree->tree_stats().output();
+
+        } // tree_tp
+
+      } // max elems/leaf
+
+    } // max depth
+
+  } // # elements
+
+  
+#ifdef USE_MPI
+  fail = MPI_Finalize();
+  if (fail) return fail;
+#endif
+
+  return 0;
+}
+
+ErrorCode test_locator(SpatialLocator &sl, int npoints, double &cpu_time, double &percent_outside) 
+{
+  BoundBox box;
+  ErrorCode rval = sl.get_bounding_box(box);
+  if (MB_SUCCESS != rval) return rval;
+  CartVect box_del = box.bMax - box.bMin;
+
+  std::vector<CartVect> test_pts(npoints), test_res(npoints);
+  std::vector<EntityHandle> ents(npoints);
+  bool *is_in = new bool[npoints];
+
+  double denom = 1.0 / (double)RAND_MAX;
+  for (int i = 0; i < npoints; i++) {    
+      // generate a small number of random point to test
+    double rx = (double)rand() * denom, ry = (double)rand() * denom, rz = (double)rand() * denom;
+    test_pts[i] = box.bMin + CartVect(rx*box_del[0], ry*box_del[1], rz*box_del[2]);
+  }
+  
+  CpuTimer ct;
+  
+    // call spatial locator to locate points
+  rval = sl.locate_points(test_pts[0].array(), npoints, &ents[0], test_res[0].array(), 0.0, 0.0, &is_in[0]);
+  if (MB_SUCCESS != rval) return rval;
+
+  cpu_time = ct.time_elapsed();
+
+  int num_out = std::count(is_in, is_in+npoints, false);
+  percent_outside = ((double)num_out)/npoints;
+  delete [] is_in;
+  
+  return rval;
+}
+
+ErrorCode create_hex_mesh(Interface &mb, Range &elems, int n, int dim) 
+{
+  ScdInterface *scdi;
+  ErrorCode rval = mb.query_interface(scdi);
+  if (MB_SUCCESS != rval) return rval;
+  
+  HomCoord high(n-1, -1, -1);
+  if (dim > 1) high[1] = n-1;
+  if (dim > 2) high[2] = n-1;
+  ScdBox *new_box;
+  rval = scdi->construct_box(HomCoord(0, 0, 0), high, NULL, 0, new_box);
+  if (MB_SUCCESS != rval) return rval;
+  rval = mb.release_interface(scdi);
+  if (MB_SUCCESS != rval) return rval;
+
+  rval = mb.get_entities_by_dimension(0, dim, elems);
+  if (MB_SUCCESS != rval) return rval;
+
+  return rval;
+}

diff --git a/test/spatial_locator_test.cpp b/test/spatial_locator_test.cpp
index 547f908..31bf08a 100644
--- a/test/spatial_locator_test.cpp
+++ b/test/spatial_locator_test.cpp
@@ -5,6 +5,8 @@
 #include "moab/ScdInterface.hpp"
 #include "moab/CartVect.hpp"
 #include "moab/BVHTree.hpp"
+#include "moab/ProgOptions.hpp"
+#include "moab/CpuTimer.hpp"
 
 #ifdef USE_MPI
 #include "moab_mpi.h"
@@ -13,16 +15,21 @@
 #include "TestUtil.hpp"
 
 #include <cstdlib>
+#include <sstream>
 
 using namespace moab;
 
-const int npoints = 1000;
-
 void test_kd_tree();
 void test_bvh_tree();
 void test_locator(SpatialLocator *sl);
 
-ErrorCode create_hex_mesh(Interface &mb, Range &elems, int n = 10, int dim = 3);
+ErrorCode create_hex_mesh(Interface &mb, Range &elems, int n, int dim);
+
+int max_depth = 30;
+int npoints = 1000;
+int leaf = 6;
+bool print_tree = false;
+int ints = 10;
 
 int main(int argc, char **argv)
 {
@@ -34,6 +41,14 @@ int main(int argc, char **argv)
   argv[0]=argv[argc-argc];
 #endif
 
+  ProgOptions po("spatial_locator_test options" );
+  po.addOpt<int>( "ints,i", "Number of intervals on each side of scd mesh", &ints);
+  po.addOpt<int>( "leaf,l", "Maximum number of elements per leaf", &leaf);
+  po.addOpt<int>( "max_depth,m", "Maximum depth of tree", &max_depth);
+  po.addOpt<int>( "npoints,n", "Number of query points", &npoints);
+  po.addOpt<void>( "print,p", "Print tree details", &print_tree);
+  po.parseCommandLine(argc, argv);
+
   RUN_TEST(test_kd_tree);
   RUN_TEST(test_bvh_tree);
   
@@ -52,7 +67,7 @@ void test_kd_tree()
   
     // create a simple mesh to test
   Range elems;
-  rval = create_hex_mesh(mb, elems); CHECK_ERR(rval);
+  rval = create_hex_mesh(mb, elems, ints, 3); CHECK_ERR(rval);
 
     // initialize spatial locator with the elements and the default tree type
   SpatialLocator *sl = new SpatialLocator(&mb, elems);
@@ -70,10 +85,14 @@ void test_bvh_tree()
   
     // create a simple mesh to test
   Range elems;
-  rval = create_hex_mesh(mb, elems); CHECK_ERR(rval);
+  rval = create_hex_mesh(mb, elems, ints, 3); CHECK_ERR(rval);
 
     // initialize spatial locator with the elements and a BVH tree
   BVHTree bvh(&mb);
+  std::ostringstream opts;
+  opts << "MAX_DEPTH=" << max_depth << ";MAX_PER_LEAF=" << leaf;
+  FileOptions fo(opts.str().c_str());
+  rval = bvh.parse_options(fo);
   SpatialLocator *sl = new SpatialLocator(&mb, elems, &bvh);
   test_locator(sl);
   
@@ -104,10 +123,13 @@ void test_locator(SpatialLocator *sl)
   }
 
   std::cout << "Traversal stats:" << std::endl;
-  sl->get_tree()->tree_stats().print();
+  sl->get_tree()->tree_stats().output();
 
-  std::cout << "Tree information: " << std::endl;
-  rval = sl->get_tree()->print();
+  if (print_tree) {
+    std::cout << "Tree information: " << std::endl;
+    rval = sl->get_tree()->print();
+    CHECK_ERR(rval);
+  }
 }
 
 ErrorCode create_hex_mesh(Interface &mb, Range &elems, int n, int dim) 

diff --git a/tools/dagmc/DagMC.cpp b/tools/dagmc/DagMC.cpp
index d50c615..87f84cb 100755
--- a/tools/dagmc/DagMC.cpp
+++ b/tools/dagmc/DagMC.cpp
@@ -4,7 +4,7 @@
 #include "moab/Range.hpp"
 #include "moab/Core.hpp"
 #include "moab/GeomUtil.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 
 #ifdef CGM
 #include "InitCGMA.hpp"

diff --git a/tools/mbcoupler/ssn_test.cpp b/tools/mbcoupler/ssn_test.cpp
index 8bb606b..16d3fe4 100644
--- a/tools/mbcoupler/ssn_test.cpp
+++ b/tools/mbcoupler/ssn_test.cpp
@@ -2,7 +2,7 @@
 #include "moab/ParallelComm.hpp"
 #include "MBParallelConventions.h"
 #include "moab/Core.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "ReadParallel.hpp"
 #include "Coupler.hpp"
 #include "iMesh_extensions.h"


https://bitbucket.org/fathomteam/moab/commits/d1df4716fdb8/
Changeset:   d1df4716fdb8
Branch:      None
User:        tautges
Date:        2013-07-15 18:34:26
Summary:     Merged fathomteam/moab into master
Affected #:  57 files

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3774046..007d501 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -100,7 +100,30 @@ project( MOAB )
   # iMesh
   option ( MOAB_BUILD_IMESH        "Build the iMesh interface?"           ON )
 
+  # check for MPI package
+  if ( MOAB_USE_MPI )
+    find_package( MPI )
+    # CMake FindMPI script is sorely lacking:
+    if ( MPI_LIBRARY AND MPI_INCLUDE_PATH )
+      set( MPI_FOUND 1 )
+    endif ( MPI_LIBRARY AND MPI_INCLUDE_PATH )
+
+    if ( MPI_FOUND )
+      set ( MOAB_DEFINES "${MOAB_DEFINES} -DUSE_MPI" )
+    endif ( MPI_FOUND )
+  endif ( MOAB_USE_MPI )
+
+  if ( MOAB_USE_NETCDF )
+    find_package( NetCDF )
+  endif ( MOAB_USE_NETCDF )
+
+  if ( MOAB_USE_HDF )
+    # HDF5
+    find_package( HDF5 )
+  endif ( MOAB_USE_HDF )
+
   add_subdirectory( src )
+  add_subdirectory( itaps/imesh )
   add_subdirectory( tools )
   add_subdirectory( test )
-  
+

diff --git a/MeshFiles/unittest/Makefile.am b/MeshFiles/unittest/Makefile.am
index f347315..16dc2ed 100644
--- a/MeshFiles/unittest/Makefile.am
+++ b/MeshFiles/unittest/Makefile.am
@@ -21,6 +21,8 @@ EXTRA_DIST  = 125hex.g \
               testtet.g \
 	      ptest.cub \
               64bricks_512hex.h5m \
+              64bricks_1khex.h5m\
+              64bricks_12ktet.h5m\
               partBed.smf \
               PB.h5m  \
               polyPB.txt \
@@ -28,5 +30,7 @@ EXTRA_DIST  = 125hex.g \
               quads.h5m \
               SECrop2.h5m \
               poly14.txt \
-              BedCrop2.h5m
+              BedCrop2.h5m \
+              mpas_p8.h5m \
+              Homme_2pt.h5m
 

diff --git a/MeshFiles/unittest/io/Makefile.am b/MeshFiles/unittest/io/Makefile.am
index 8257e5f..fb8a265 100644
--- a/MeshFiles/unittest/io/Makefile.am
+++ b/MeshFiles/unittest/io/Makefile.am
@@ -18,6 +18,7 @@ EXTRA_DIST = HommeMapping.nc \
              test.nas \
              test.unv \
 	     sample.stl \
-             three.smf
+             three.smf \
+             mpasx1.642.t.2.nc
 
 

diff --git a/MeshFiles/unittest/io/mpasx1.642.t.2.nc b/MeshFiles/unittest/io/mpasx1.642.t.2.nc
new file mode 100644
index 0000000..f1e8c94
Binary files /dev/null and b/MeshFiles/unittest/io/mpasx1.642.t.2.nc differ

diff --git a/MeshFiles/unittest/mpas_p8.h5m b/MeshFiles/unittest/mpas_p8.h5m
new file mode 100644
index 0000000..75662d2
Binary files /dev/null and b/MeshFiles/unittest/mpas_p8.h5m differ

diff --git a/doc/DG/moabDG.h b/doc/DG/moabDG.h
new file mode 100644
index 0000000..1091094
--- /dev/null
+++ b/doc/DG/moabDG.h
@@ -0,0 +1,1094 @@
+/*! \page developerguide Developer's Guide (MOAB 4.6)
+ 
+  \subpage dg-contents
+ 
+  \subpage dg-figures
+
+  \subpage dg-tables
+*/
+
+/*!  \page dg-contents Table of Contents
+
+  \subpage sequence-info
+
+  \subpage meta-data-info
+*/
+
+/*!  \page dg-figures List of Figures
+
+    \ref figure1
+
+    \ref figure2
+
+    \ref figure3
+*/
+
+/*!  \page dg-tables List of Tables
+
+    \ref table1
+
+    \ref table2
+
+    \ref table3
+
+    \ref table4
+
+    \ref table5
+
+    \ref table6
+
+*/
+
+/*!  \page sequence-info Sequence Info
+
+  \ref sequence
+
+  \ref manager
+
+  \ref s-mesh
+
+  \ref sets
+
+  \section sequence  EntitySequence & SequenceData 
+
+  \subsection figure1 Figure 1: EntitySequences For One SequenceData
+The <I>SequenceData</I> class manages as set of arrays of per-entity values. Each
+<I>SequenceData</I> has a start and end handle denoting the block of entities for which
+the arrays contain data. The arrays managed by a <I>SequenceData</I> instance are
+divided into three groups:
+
+- Type-specific data (connectivity, coordinates, etc.): zero or more arrays.
+- Adjacency data: zero or one array.
+- Dense tag data: zero or more arrays.
+.
+
+The abstract <I>EntitySequence</I> class is a non-strict subset of a <I>SequenceData</I>.
+It contains a pointer to a <I>SequenceData</I> and the start and end handles to indi-
+cate the subset of the referenced <I>SequenceData</I>. The <I>EntitySequence</I> class is
+used to represent the regions of valid (or allocated) handles in a <I>SequenceData</I>.
+A <I>SequenceData</I> is expected to be referenced by one or more <I>EntitySequence</I>
+instances.
+
+Initial <I>EntitySequence</I> and <I>SequenceData</I> pairs are typically created in one
+of two configurations. When reading from a file, a <I>SequenceData</I> will be created
+to represent all of a single type of entity contained in a file. As all entries in the <I>SequenceData</I> correspond to valid handles (entities read from the file) a single
+<I>EntitySequence</I> instance corresponding to the entire <I>SequenceData</I> is initially
+created. The second configuration arises when allocating a single entity. If no
+entities have been allocated yet, a new <I>SequenceData</I> must be created to store
+the entity data. It is created with a constant size (e.g. 4k entities). The new
+<I>EntitySequence</I> corresponds to only the first entity in the <I>SequenceData</I>: the
+one allocated entity. As subsequent entities are allocated, the <I>EntitySequence</I>
+is extended to cover more of the corresponding <I>SequenceData</I>.
+
+Concrete subclasses of the <I>EntitySequence</I> class are responsible for rep-
+resenting specific types of entities using the array storage provided by the
+<I>SequenceData</I> class. They also handle allocating <I>SequenceData</I> instances with
+appropriate arrays for storing a particular type of entity. Each concrete subclass
+typically provides two constructors corresponding to the two initial allocation
+configurations described in the previous paragraph. <I>EntitySequence</I> imple-
+mentations also provide a split method, which is a type of factory method. It
+modifies the called sequence and creates a new sequence such that the range of
+entities represented by the original sequence is split.
+
+The <I>VertexSequence</I> class provides an <I>EntitySequence</I> for storing ver-
+tex data. It references a SequenceData containing three arrays of doubles
+for storing the blocked vertex coordinate data. The <I>ElementSequence</I> class
+extends the <I>EntitySequence</I> interface with element-specific functionality. The
+<I>UnstructuredElemSeq</I> class is the concrete implementation of <I>ElementSequence</I>
+used to represent unstructured elements, polygons, and polyhedra. <I>MeshSetSequence</I>
+is the <I>EntitySequence</I> used for storing entity sets.
+
+Each <I>EntitySequence</I> implementation also provides an implementation of
+the values per entity method. This value is used to determine if an exist-
+ing <I>SequenceData</I> that has available entities is suitable for storing a particular
+entity. For example, <I>UnstructuredElemSeq</I> returns the number of nodes per el-
+ement from values per entity. When allocating a new element with a specific
+number of nodes, this value is used to determine if that element may be stored
+in a specific <I>SequenceData</I>. For vertices, this value is always zero. This could
+be changed to the number of coordinates per vertex, allowing representation of
+mixed-dimension data. However, API changes would be required to utilize such
+a feature. Sequences for which the corresponding data cannot be used to store
+new entities (e.g. structured mesh discussed in a later section) will return -1 or
+some other invalid value.
+
+ \ref sequence-info "Top"
+
+  \section manager TypeSequenceManager & SequenceManager 
+
+The <I>TypeSequenceManager</I> class maintains an organized set of <I>EntitySequence</I>
+instances and corresponding <I>SequenceData</I> instances. It is used to manage
+all such instances for entities of a single <I>EntityType</I>. <I>TypeSequenceManager</I>
+enforces the following four rules on its contained data:
+
+-# No two <I>SequenceData</I> instances may overlap.  
+-# No two <I>EntitySequence</I> instances may overlap.
+-# Every <I>EntitySequence</I> must be a subset of a <I>SequenceData</I>.
+-# Any pair of <I>EntitySequence</I> instances referencing the same <I>SequenceData</I> must be separated by at least one unallocated handle.
+.
+
+  \subsection figure2 Figure 2: SequenceManager and Related Classes
+
+The first three rules are required for the validity of the data model. The
+fourth rule avoids unnecessary inefficiency. It is implemented by merging such
+adjacent sequences. In some cases, other classes (e.g. <I>SequenceManager</I>) can
+modify an <I>EntitySequence</I> such that the fourth rule is violated. In such cases,
+the <I>TypeSequenceManager::notify</I> prepended or <I>TypeSequenceManager::notify</I> appended
+method must be called to maintain the integrity of the data<sup>1</sup>. The above rules
+(including the fourth) are assumed in many other methods of the <I>TypeSequenceManager</I>
+class, such that those methods will fail or behave unexpectedly if the managed
+data does not conform to the rules.
+
+<I>TypeSequenceManager</I> contains three principal data structures. The first is
+a <I>std::set</I> of <I>EntitySequence</I> pointers sorted using a custom comparison op-
+erator that queries the start and end handles of the referenced sequences. The
+comparison operation is defined as: <I>a->end_handle() < b->start_handle()</I>.
+This method of comparison has the advantage that a sequence corresponding to
+a specific handle can be located by searching the set for a “sequence” beginning
+and ending with the search value. The lower bound and find methods pro-
+vided by the library are guaranteed to return the sequence, if it exists. Using
+such a comparison operator will result in undefined behavior if the set contains
+overlapping sequences. This is acceptable, as rule two above prohibits such
+a configuration. However, some care must be taken in writing and modifying
+methods in <I>TypeSequenceManager</I> so as to avoid having overlapping sequences
+as a transitory state of some operation.
+
+The second important data member of <I>TypeSequenceManager</I> is a pointer
+to the last referenced <I>EntitySequence</I>. This “cached” value is used to speed up
+searches by entity handle. This pointer is never null unless the sequence is empty.
+This rule is maintained to avoid unnecessary branches in fast query paths. In
+cases where the last referenced sequence is deleted, <I>TypeSequenceManager</I> will
+typically assign an arbitrary sequence (e.g. the first one) to the last referenced
+pointer.
+
+The third data member of <I>TypeSequenceManager</I> is a <I>std::set</I> of <I>SequenceData</I>
+instances that are not completely covered by a <I>EntitySequence</I> instance<sup>2</sup>.
+This list is searched when allocating new handles. <I>TypeSequenceManager</I> also
+embeds in each <I>SequenceData</I> instance a reference to the first corresponding
+<I>EntitySequence</I> so that it may be located quickly from only the <I>SequenceData</I>
+pointer.
+
+The <I>SequenceManager</I> class contains an array of <I>TypeSequenceManager</I> in-
+stances, one for each <I>EntityType</I>. It also provides all type-specific operations
+such as allocating the correct <I>EntitySequence</I> subtype for a given <I>EntityType</I>.
+
+<sup>1</sup>This source of potential error can be eliminated with changes to the entity set representation. This is discussed in a later section.
+
+<sup>2</sup>Given rule four for the data managed by a <I>TypeSequenceManager</I>, any <I>SequenceData</I> for which all handles are allocated will be referenced by exactly one <I>EntitySequence</I>.
+
+  \ref sequence-info "Top"
+
+ \section s-mesh Structured Mesh
+
+Structured mesh storage is implemented using subclasses of <I>SequenceData</I>:
+<I>ScdElementData</I> and <I>ScdVertexData</I>. The <I>StructuredElementSeq</I> class is
+used to access the structured element connectivity. A standard <I>VertexSequence</I>
+instance is used to access the ScdVertexData because the vertex data storage
+is the same as for unstructured mesh.
+
+  \ref sequence-info "Top"
+
+  \section sets Entity Sets
+
+- MeshSetSequence
+
+The <I>MeshSetSequence</I> class is the same as most other subclasses of <I>EntitySequence</I>
+in that it utilizes SequenceData to store its data. A single array in the <I>SequenceData</I>
+is used to store instances of the MeshSet class, one per allocated <I>EntityHandle</I>.
+<I>SequenceData</I> allocates all of its managed arrays using malloc and free as
+simple arrays of bytes. <I>MeshSetSequence</I> does in-place construction and de-
+struction of <I>MeshSet</I> instances within that array. This is similar to what is
+done by <I>std::vector</I> and other container classes that may own more storage
+than is required at a given time for contained objects.
+
+- MeshSet
+
+  \subsection figure3 Figure 3: SequenceManager and Related Classes
+
+The <I>MeshSet</I> class is used to represent a single entity set instance in MOAB.
+The class is optimized to minimize storage (further possible improvements in
+storage size are discussed later.)
+
+Figure 3 shows the memory layout of an instance of the <I>MeshSet</I> class.
+The flags member holds the set creation bit flags: <I>MESHSET_TRACK_OWNER</I>,
+<I>MESHSET_SET</I>, and <I>MESHSET_ORDERED</I>. The presence of the <I>MESHSET_TRACK_OWNER</I>
+indicates that reverse links from the contained entities back to the owning set
+should be maintained in the adjacency list of each entity. The <I>MESHSET_SET</I>
+and <I>MESHSET_ORDERED</I> bits are mutually exclusive, and as such most code only
+tests for the <I>MESHSET_ORDERED</I>, meaning that in practice the <I>MESHSET_SET</I> bit is
+ignored. <I>MESHSET_ORDERED</I> indicates that the set may contain duplicate handles
+and that the order that the handles are added to the set should be preserved.
+In practice, such sets are stored as a simple list of handles. <I>MESHSET_SET</I> (or in
+practice, the lack of <I>MESHSET_ORDERED</I>) indicates that the order of the handles
+need not be preserved and that the set may not contain duplicate handles. Such
+sets are stored in a sorted range-compacted format similar to that of the Range
+class.
+
+The memory for storing contents, parents, and children are each handled in
+the same way. The data in the class is composed of a 2-bit ‘size’ field and two
+values, where the two values may either be two handles or two pointers. The size
+bit-fields are grouped together to reduce the required amount of memory. If the
+numerical value of the 2-bit size field is 0 then the corresponding list is empty.
+If the 2-bit size field is either 1 or 2, then the contents of the corresponding list
+are stored directly in the corresponding two data fields of the MeshSet object.
+If the 2-bit size field has a value of 3 (11 binary), then the corresponding two
+data fields store the begin and end pointers of an external array of handles.
+The number of handles in the external array can be obtained by taking the
+difference of the start and end pointers. Note that unlike <I>std::vector</I>, we
+do not store both an allocated and used size. We store only the ‘used’ size
+and call std::realloc whenever the used size is modified, thus we rely on the
+std::malloc implementation in the standard C library to track ‘allocated’ size
+for us. In practice this performs well but does not return memory to the ‘system’
+when lists shrink (unless they shrink to zero). This overall scheme could exhibit
+poor performance if the size of one of the data lists in the set frequently changes
+between less than two and more than two handles, as this will result in frequent
+releasing and re-allocating of the memory for the corresponding array.
+
+If the <I>MESHSET_ORDERED</I> flag is not present, then the set contents list (parent
+and child lists are unaffected) is stored in a range-compacted format. In this
+format the number of handles stored in the array is always a multiple of two.
+Each consecutive pair of handles indicate the start and end, inclusive, of a range
+of handles contained in the set. All such handle range pairs are stored in sorted
+order and do not overlap. Nor is the end handle of one range ever one less than
+the start handle of the next. All such ‘adjacent’ range pairs are merged into a
+single pair. The code for insertion and removal of handles from range-formatted
+set content lists is fairly complex. The implementation will guarantee that a
+given call to insert entities into a range or remove entities from a range is never
+worse than O(ln n) + O(m + n), where ‘n’ is the number of handles to insert
+and ‘m’ is the number of handles already contained in the set. So it is generally
+much more efficient to build Ranges of handles to insert (and remove) and call
+MOAB to insert (or remove) the entire list at once rather than making may
+calls to insert (or remove) one or a few handles from the contents of a set.
+The set storage could probably be further minimized by allowing up to six
+handles in one of the lists to be elided. That is, as there are six potential ‘slots’
+in the MeshSet object then if two of the lists are empty it should be possible to store up to six values of the remaining list directly in the MeshSet object.
+However, the additional runtime cost of such complexity could easily outweigh
+any storage advantage. Further investigation into this has not been done because
+the primary motivation for the storage optimization was to support binary trees.
+
+Another possible optimization of storage would be to remove the <I>MeshSet</I>
+object entirely and instead store the data in a ‘blocked’ format. The corre-
+sponding <I>SequenceData</I> would contain four arrays: flags, parents, children, and
+contents instead of a single array of <I>MeshSet</I> objects. If this were done then
+no storage need ever be allocated for parent or child links if none of the sets
+in a <I>SequenceData</I> has parent or child links. The effectiveness of the storage
+reduction would depend greatly on how sets get grouped into <I>SequenceDatas</I>.
+This alternate storage scheme might also allow for better cache utilization as it
+would group like data together. It is often the case that application code that
+is querying the contents of one set will query the contents of many but never
+query the parents or children of any set. Or that an application will query only
+parent or child links of a set without every querying other set properties. The
+downside of this solution is that it makes the implementation a little less mod-
+ular and maintainable because the existing logic contained in the <I>MeshSet</I> class
+would need to be spread throughout the <I>MeshSetSequence</I> class.
+
+  \ref sequence-info "Top"
+*/
+
+/*! \page meta-data-info I/O and Meta-Data Storage Conventions in MOAB
+
+  <Center><H3> Timothy J. Tautges </H3></Center>
+
+    \ref meta-introduction
+
+    \ref meta-conventions
+
+    \ref meta-options
+
+    \ref meta-references
+
+    \ref appendixA
+
+    \ref appendixB
+
+    \ref appendixC
+
+    \ref appendixD
+
+    \ref appendixE
+
+  \section meta-introduction  Introduction
+
+The Mesh-Oriented datABase (MOAB) is a library for representing finite element and other types of mesh data [1].  Various types of meta-data are often used in conjunction with a mesh.  Examples include boundary condition groupings, material types, and provenance information for the mesh.  Because the data model used in MOAB is so abstract, conventions are useful for describing how meta-data is stored into that data model.  This document describes those conventions for several types of data commonly found in meshes stored in MOAB.  Because the data models used by MOAB and iMesh, the ITAPS mesh interface [2], are so similar, the conventions described here apply almost unmodified to iMesh as well as to MOAB.
+
+The meshes represented in MOAB originate in a variety of forms, including mesh read from files of various formats (e.g. CUBIT “.cub” file, VTK, etc.) as well as mesh written into MOAB directly by various software libraries (e.g. MeshKit).  Although there is no standard for naming or storing meta-data with a mesh, there is a great deal of commonality in the types of meta-data typically found with mesh data.  This document describes conventions that have been established for commonly encountered meta-data.  Various mesh readers implemented in MOAB attempt to read meta-data from a file and write it into the MOAB data model using these conventions.  Although there is no requirement to store a given type of meta-data in the form described here, a number of services have been written to handle meta-data using these conventions, no matter the source of the meta-data being processed.
+
+Several specific tools are often used in concert with MOAB and bear special mention here.  The CUBIT toolkit generates finite element meshes, and saves them to a native save file (referred to as a “.cub” file) which MOAB is able to read.  Reading CUBIT meshes into MOAB through the .cub file format is preferred over other formats, since most other mesh formats written by CUBIT do not save most meta-data.  The MeshKit library also generates mesh using CGM and MOAB, and uses the same conventions for storing meshes into MOAB.  Finally, MOAB includes a CGM reader which can read a geometric model into a faceted representation in MOAB.  Meta-data from all these tools are stored in MOAB using the conventions described here. 
+
+The MOAB data model consists of the following basic types:
+- <B>Entity</B>: The basic elements of topology, e.g. vertex, edge, triangle, tetrahedron, etc.  MOAB represents all types in the finite element zoo, plus polygons and polyhedra.
+- <B>Entity Set</B>: An arbitrary collection of entities and other sets.  Sets can have parent/child relations with other sets, and these relations are distinct from “contains” relations.
+- <B>Interface</B>: The interface object through which other entities are accessed, in the sense of object-oriented-programming.  iMesh refers to the interface as the “root” set.
+- <B>Tag</B>: A piece of data that can be assigned a distinct value to each entity and entity set, and to the interface itself.  Tags have a prescribed name, size in bytes, and data type; allowed data types are integer, double, entity handle, and byte or opaque.
+.
+
+The following section describes each meta-data tag convention in detail; these conventions are also summarized in Table 1.
+
+  \ref meta-data-info "Top"
+
+  \section meta-conventions  Meta-Data Conventions
+
+Meta-data is stored in MOAB and iMesh in the form of tags applied to either entities or entity sets.  For meta-data represented as entity sets, the contents of those sets are determined by the convention, with tags on those sets identifying them with the convention and adding any other semantic data.
+
+Each meta-data convention is described in a subsection below.  Each convention begins with a short description of:
+- Whether tags associated with the convention are assigned to entities or entity sets
+- The tag(s) associated with the convention; information for each tag includes the name, the data type (I=integer, D=double, C=character, H=handle), and the tag length.  Tag lengths are specified after an asterisk (*); for example, C*32 implies a tag with character type and length 32.  Unspecified lengths correspond to length one.
+.
+
+<H3>Name</H3>
+
+(Data: Entity sets, entities; Tag(s): NAME/C*32)
+
+Character strings are used in many different contexts in applications.  MOAB uses the “NAME” tag to store character strings used to name entities.  This tag is of byte-type and is of length 32 bytes.  Note that the string stored in this tag may or may not be terminated with a NULL character.  It is always prudent account for missing NULL terminator, to avoid buffer overflow errors in the application.  Applications are free to define their own version of the NAME tag with a longer length, though this definition may conflict with other services attempting to use this tag with the conventional size.  Applications needing a string tag with a longer or variable length can also use MOAB’s variable-length tag type, though this will not be compatible with iMesh.
+
+<H3>Title </H3>
+
+(Data: Entity sets (file or instance); Tag(s): TITLE/C*strlen)
+
+The title tag is meant to hold the overall identifier of a mesh, written at generation time or read from a file generated with a non-MOAB tool.  The tag length is variable, and is set by the application directly (by calling the tag_create function) or indirectly (by embedding the title in a file read by MOAB).
+
+<H3> Global Identifier </H3>
+
+(Data: Entity sets, entities; Tag(s): GLOBAL_ID/I)
+
+Global identifiers are used in many different contexts in applications.  Geometric model entities are identified by dimension and id, e.g. “Volume 1”.  Mesh vertices and elements are identified similarly in mesh generation codes.  Boundary conditions and material types are identified similarly.  This tag is used to store such information.  This tag is currently stored in a 32-byte integer, though this may change in the future.
+
+<H3> Geometric Model Information </H3>
+
+(Data: Entity sets; Tag(s): GEOM_DIMENSION/I, GLOBAL_ID/I, NAME/C*32, CATEGORY/C*32, GEOM_SENSE_2(EH[2]), GEOM_SENSE_N_ENTS(EH*N), GEOM_SENSE_N_SENSES(I*N))
+
+Mesh generation is often performed starting from a geometric model, represented in some form of CAD engine.  Many of the meshes used by MOAB are generated based on the CGM library.  Geometric models contain both topological information (the topological entities in the geometric model) and shape information (the geometric shape of those entities), as well as other meta-data written to the entities in a model.  When a mesh is read from a CUBIT .cub file, meta-data from the geometric model is read and represented in the MOAB data model, as described below. <B> Note that although MOAB reads and represents meta-data associated with the geometric model, it does not represent the geometric model itself.</B>  Therefore, shape-related information, e.g. the arc length of an edge or surface normal at a given point, can be retrieved only from the model represented in CGM or another geometric modeling engine.
+
+The information contained in a geometric model, read into and represented in MOAB, consists of:
+- Model entities (vertex, edge, face, volume)
+- Topological relationships between model entities
+- Groups of model entities
+- Model entity/group ids
+- Model entity/group names
+.
+The storage of this information into MOAB's data model is described for each type is described below.
+
+- <B>Entities </B>
+
+Entities in the geometric model (VERTEX, EDGE, FACE, VOLUME) are each represented by an entity set<sup>1</sup>.  These sets are tagged with the “GEOM_DIMENSION” tag, with integer value equal to the topological dimension of the entity (VERTEX = 0, EDGE = 1, etc.)  These sets contain the mesh owned by the corresponding entity in the geometric model.  Note this does not include mesh owned by bounding entities; thus, the set for a FACE will not contain the mesh vertices owned by bounding EDGEs in the geometric model.  These sets may or may not contain mesh entities of intermediate dimension, e.g. mesh edges owned by a FACE or faces owned by a VOLUME, depending on the application generating the mesh or the file from which the mesh was read.  These sets are all set-types, i.e. the order of entities in the sets is not significant, except in the case of EDGE sets, where order of the mesh vertices and edges corresponds to the relative order of vertices and edges at the time of mesh generation.  In MOAB, these sets are non-tracking by default, i.e. entities do not have knowledge of which geometry sets they are members of.
+
+<sup>1</sup>Body-type entities from CUBIT are not explicitly represented in MOAB.
+
+- <B> Topological Relationships </B>
+
+In the geometric model, each FACE is bounded by zero or more EDGEs; other topological relationships between geometric entities exist in a similar manner.  These relationships are embedded in the data model using parent/child relations between entity sets.  For example, the entity set corresponding to a FACE will have child sets, each corresponding to a bounding EDGE, and parent sets, each corresponding to a VOLUME bounded by that FACE.  The relative order of sets in those parent/child lists is not significant, thus, “loops” bounding a FACE cannot reliably be inferred from this data.
+
+- <B> Groups </B>
+
+Geometric entities are sometimes assigned to application-specific groups.  These groups are represented using entity sets, tagged with a “GROUP” tag whose value equals the group id.  Group sets are “set”-type, and are not tracking sets.  These sets contain the sets corresponding to geometric entities contained in the groups in the geometric model, as well as any mesh entities assigned to the group.
+
+<H4> Sense </H4>
+
+A geometric face has a natural orientation, indicated by the direction of the normal to the face; similarly, edges have a natural orientation determined by the direction of the tangent.  When faces bound regions, or edges bound faces, they do so with a sense; if a region includes a face with forward sense, that means the face's natural normal direction points out of the volume.  If a face includes an edge with forward sense, that means that if one moves along the edge in the direction of its tangent, the material of the face is on the left hand side.  The sense of a face (edge) with respect to a region (face) it bounds is stored using tags on the face (edge).
+
+Most models allow a face to be part of only two regions.  Therefore, to store the sense of a face with respect to regions including it, a tag with two values is used.  This tag is named GEOM_SENSE_2, and has 2 EntityHandle values.  The first value corresponds to the entity set for the region for which that face has a forward sense, and the second to the region for which that face has a reverse sense.
+
+Edges can bound more than two faces.  Therefore, two variable-length tags are used, one to store the EntityHandles of the faces the edge bounds, and the other to store the sense with which the edge bounds the corresponding face.  These tags are named GEOM_SENSE_N_ENTS and GEOM_SENSE_N_SENSES, respectively.  These are stored as variable-length tags; see the MOAB user's guide for information on how to work with tags of this type. 
+
+The following sense values are used:
+- 0: forward
+- 1: reverse
+- -1: unnknown
+
+<H3> Material Type </H3>
+
+(Data: Entity sets; Tag(s): MATERIAL_SET/I)
+
+Most finite element and other PDE-based analysis codes require a material type for each cell or element in the simulation.  MOAB uses entity sets to store this information, in the form of entity sets.  The MATERIAL_SET tag is used to identify these sets.  The value of this tag is conventionally an integer; in most cases this stores a user-assigned identifier associated with that material. 
+
+CUBIT assigns material types using what it calls “element blocks”, with each element block given a user-assigned id number and optionally a name.  The CUBIT and Exodus file readers in MOAB read element blocks into MATERIAL_SET sets.  
+
+In CUBIT, materials are typically assigned by assigning geometric volumes to element blocks.  Therefore, material sets often contain entity sets corresponding to those volumes.  Thus, a materrial set in MOAB is unlikely to contain mesh entities directly; rather, that set contains other sets which contain mesh entities.  In these cases, mesh entities can be retrieved by passing a “recursive” flag to the appropriate function (MOAB), or by calling the getEntitiesRec extension function (iMesh) provided by MOAB.
+
+<H3> Boundary Conditions (Dirichlet, Neumann)</H3>
+
+Data: Entity sets; Tag(s): DIRICHLET_SET/I, NEUMANN_SET/I)
+
+Boundary conditions are often specified in terms of geometric model entities, similar to material types.  MOAB uses entity sets to store this information as well.  The DIRICHLET_SET and NEUMANN_SET tags are used to represent Dirichlet- and Neumann-type boundary condition sets, resp.  By convention, Neumann sets usually contain (indirectly) intermediate-dimension entities like edges in a 2D mesh or faces in a 3D mesh, while Dirichlet sets usually contain vertices.  In addition, Neumann sets are represented as sets of faces, rather than as sides of elements.  Faces can be ordered “forward” or “reverse” with respect to one of the bounding elements, depending on whether the right-hand normal points into or out of the element.  Forward-sense faces are added to the Neumann set.  Reverse-sense faces are put into a separate set; that set is tagged with the NEUSET_SENSE tag, with value = -1; and that reverse set is added to the Neummann set.
+
+<H3> Parallel Mesh Constructs </H3>
+
+(Data: Entity sets, entities; Tag(s): PARALLEL_PART/I, PARALLEL_PARTITION/I, PSTATUS/C*1, PARALLEL_SHARED_PROC/I, PARALLEL/SHARED_HANDLE/H, PARALLEL_SHARED_PROCS/I*NP, PARALLEL_SHARED_HANDLES/H*NP)
+
+On a parallel computer, MOAB can represent the mesh on each processor as well as information about entities shared with neighboring processors.  Some of this information is also relevant even when the mesh is represented on a serial machine.  MOAB uses several tag and set conventions to describe the parallel nature of a mesh.  This information is summarized here; for a more complete description of MOAB’s parallel mesh representation and functionality, see [ref-moabpar].
+
+- <B> Parallel partition, parts </B>
+
+Most parallel mesh applications use a domain decomposition approach, where each processor solves for a subset of the domain.  The set of entities solved by a given processor is referred to as a part, and the collection of parts together is called the partition.  MOAB stores each part in an entity set, marked with the PARALLEL_PART tag, whose value is the rank of the processor assigned that part; an entity set which contains all part sets is given the PARALLEL_PARTITION tag, whose value is currently meaningless.  The MBZoltan tool included as a tool in MOAB can partition a mesh for parallel solution, and writes the partition to the mesh in the form of parts and partitions.  Both these types of sets can be accessed in a serial mesh, e.g. for visualization.
+
+- <B> Part interfaces </B>
+
+When a partitioned mesh has been loaded on a parallel computer, the part on a given processor may share portions of its boundary with parts on other processors.  These shared regions are called part interfaces, and are also represented using entity sets.  These sets are marked with the PARALLEL_INTERFACE tag, whose value is currently meaningless.
+
+- <B> Shared processor and handle </B>
+
+For entities shared between processors, it is helpful to know locally which other processor shares an entity, and what the entity’s handle is on the remote processor.  There are two cases which are useful to distinguish, first where an entity is shared with only one other processor (referred to as shared), and second when a processor is shared by more than one other processor (referred to as multi-shared).   Shared entities are given the PARALLEL_SHARED_PROC and PARALLEL_SHARED_HANDLE tags, which store the rank of the sharing processor and the handle of the entity on that processor, respectively.  Multi-shared entities are marked with the PARALLEL_SHARED_PROCS and PARALLEL_SHARED_HANDLES tags; these tags have a length NP assigned at compile time in MOAB, with default values of -1 for processor rank and zero for handle (which are each invalid values for the corresponding data).  The processors/handles sharing a given entity are then written on the front of the arrays.  So, for example, an entity on processor rank 0, shared by processors 1 and 2, would have a PARALLEL_SHARED_PROCS tag whose values would be [1, 2, -1, -1, …], with PARALLEL_SHARED_HANDLES values of [m, n, 0, 0, …], where m and n would be the handles of that entity on processors 1 and 2.  The shared versions of these tags are “dense”, with default values which denote unshared entities.  The multi-shared tags are sparse tags in MOAB, with no default value.
+
+- <B> Parallel status </B>
+
+In addition to the tags above, MOAB also defines the PSTATUS tag, whose bits contain information about the parallel status of a given entity.  Starting with least significant bit, these bits represent whether an entity is 1) not owned, 2) shared, 3) multi-shared, 4) interface, 5) a ghost entity.  The first bit being set indicates “not owned” so that the default value for this tag, of zero, corresponds to an owned, unshared entity, which will be the state of most entities on a given processor.
+
+<H3>Structured Mesh Parameters </H3>
+
+MOAB has a structured mesh interface for creating structured mesh (see “ScdInterface.hpp” header file in MOAB source code).  Along with an internal representation that is more memory-efficient (since it does not need to store connectivity), MOAB also creates and tags entity sets with structured mesh parameters, which can be accessed through the normal tag and set interface.  The following tags are used:
+- <B>BOX_DIMS</B>: This tag stores the ijk coordinates of the lower and upper corner of the structured mesh box(es).
+- <B>GLOBAL_BOX_DIMS</B>: If specified when the structured mesh is created, a tag with this name stores the global box dimensions (which may be different than the local box dimensions).
+- <B>BOX_PERIODIC</B>: Stores whether the box is periodic in the i (BOX_PERIODIC[0]) and j (BOX_PERIODIC[1]) directions.
+- <B>__BOX_SET</B>: Pointer to the ScdBox instance corresponding to this entity set.<sup>2</sup>
+.
+Although the structured mesh is not saved as such in HDF5-format files, the entity sets and corresponding tags will be saved and restored.
+
+<sup>2</sup>The double-underscore in the tag name implies that this tag will not be saved in a file, in this case because the ScdBox instances are not preserved in a file.
+
+<H3>Spectral Mesh Constructs </H3>
+
+The Spectral Element Method (SEM) is a high-order method, using a polynomial Legendre interpolation basis with Gauss-Lobatto quadrature points, in contrast to the Lagrange basis used in (linear) finite elements.  A spectral mesh with order O contains quadrilateral or hexahedral elements comprised of (O+1)d vertices.  Spectral meshes are usually represented in one of two ways, either as coarse elements which point to an array of higher-order vertices (and with corner vertices represented in the normal manner), or as linear quads/hexes formed from the higher-order vertices, with each original coarse quad/hex represented by Od fine quads/hexes.  Similarly, the spectral variables, which are normally computed at fine vertex positions, are stored either on those vertices, or in lexicographically-ordered arrays on elements (with tag values repeated on neighboring elements).  MOAB can read spectral meshes from a variety of formats (at this time, including CAM-SE, HOMME, and Nek5000).  Which of the above two representations are controlled by read options and are indicated by certain tags:
+- SPECTRAL_MESH: read option indicating that spectral elements should be represented as coarse linear quads/hexes and each element containing an array of lexicographically-ordered vertex handles
+- TAG_SPECTRAL_ELEMENTS: read option; if given, spectral variables are represented as lexicographically-ordered arrays on elements
+- TAG_SPECTRAL_VERTICES: read option; if given, spectral variables are represented as tags on vertices
+- CONN=<filename>: in CAM-SE, the connectivity of the spectral mesh is stored by default in a file named “HommeMapping.nc”; this option can be given to read the connectivity from a different file
+- SPECTRAL_VERTICES: tag name for array of vertex handles
+- SPECTRAL_ORDER: tag name for spectral order, written to file set or (if no file set given) to interface after a spectral mesh is read
+.
+
+  \ref meta-data-info "Top"
+
+  \section meta-options Reader/Writer Options
+
+All mesh file readers and writers in MOAB take an option string as an argument.  By default, the semicolon (“;”) delimits individual options in the option string.  Options used in multiple readers are described in this section; the options enabled in specific readers/writers are described in the corresponding appendix at the end of this document.
+
+<H3>variable=<var_name>[,...]</H3>
+
+By default, all field data stored with the mesh is read with the mesh, and stored as tags on the associated mesh entities.  This option lists specific variables that should be read along with the mesh (note also the “nomesh” option, described elsewhere in this document).  The variable name listed will be read into a tag with the same name.  For time-dependent variables, the time step number will be appended to the variable name to form the tag name.  If no “timestep” or “timeval” option is given, all time steps will be read, resulting in several tags being created.  If the “nomesh” option is given, the application must pass the entity set resulting from the original mesh read in to the function, that this set must contain the mesh read only from that file.  The mesh in the file is checked against the mesh in the set to verify that the two correspond.  The special name “MOAB_ALL_VARIABLES” can be used to indicate that all variables should be read.  Multiple variable names can be specified, separated from each other by commas.
+
+<H3>nomesh </H3>
+
+Indicates that no mesh should be read from the file.  This option is used in conjunction with the “variable=” option, to read variables and assign them as tags to a previously-read mesh.  If this option is used, applications should pass an entity set to the read function, which should contain the mesh previously read from the file.
+
+<H3>timestep=<step_number>[, ...] </H3>
+
+Read the time step number whose time value is equal to or greater than the specified time value, for the specified variable(s).  Tag names for the variable(s) will be formed by appending the time step number to the variable name.  Multiple time step values can be specified, separated from each other by commas.
+
+  \ref meta-data-info "Top"
+
+  \section meta-references References
+
+[1]	T.J. Tautges, R. Meyers, K. Merkley, C. Stimpson, and C. Ernst, MOAB: A Mesh-Oriented Database, Sandia National Laboratories, 2004.
+
+[2]	L. Diachin, A. Bauer, B. Fix, J. Kraftcheck, K. Jansen, X. Luo, M. Miller, C. Ollivier-Gooch, M.S. Shephard, T. Tautges, and H. Trease, “Interoperable mesh and geometry tools for advanced petascale simulations,” Journal of Physics: Conference Series,  vol. 78, 2007, p. 012015.
+
+\ref meta-data-info "Top"
+
+  \section appendixA Appendix A: Summary
+
+  \subsection table1 Table 1: Summary of MOAB meta-data conventions.
+
+<table border="1">
+<tr>
+<th>Convention</th>
+<th>Applies to (E=ent, S=set)</th>
+<th>Tag(s) (type/length)</th>
+<th>Description</th>
+</tr>
+<tr>
+<td>Name</td>
+<td>E, S</td>
+<td>NAME/C*32</td>
+<td></td>
+</tr>
+<tr>
+<td>Title</td>
+<td>S</td>
+<td>TITLE/C*strlen</td>
+<td>Title of mesh</td>
+</tr>
+<tr>
+<td>Global identifier</td>
+<td>E, S</td>
+<td>GLOBAL_ID/I</td>
+<td></td>
+</tr>
+<tr>
+<td>Geometric topology</td>
+<td>S</td>
+<td>GEOM_DIMENSION/I, GLOBAL_ID/I,
+NAME/C*32,
+CATEGORY/C*32.
+GEOM_SENSE_2/EH[2],
+GEOM_SENSE_N_ENTS/EH*N,
+GEOM_SENSE_N_SENSES/I*N</td>
+<td>Sets contain mesh owned by that entity; parent/child links to bounded/bounding entities in geometric model</td>
+</tr>
+<tr>
+<td>Material type</td>
+<td>S</td>
+<td>MATERIAL_SET/I</td>
+<td>Set contains entities or sets assigned a common material type</td>
+</tr>
+<tr>
+<td>Boundary condition</td>
+<td>S</td>
+<td>DIRICHLET_SET/I, NEUMANN_SET/I</td>
+<td>Set contains entities or sets assigned a particular boundary condition; neumann sets usually contain edges (2D) or faces (3D)</td>
+</tr>
+<tr>
+<td>Parallel mesh constructs</td>
+<td>E, S</td>
+<td>PARALLEL_PART/I, PARALLEL_PARTITION/I, PSTATUS/C*1, PARALLEL_SHARED_PROC/I, PARALLEL/SHARED_HANDLE/H, PARALLEL_SHARED_PROCS/I*NP, PARALLEL_SHARED_HANDLES/H*NP</td>
+<td> Data which describes parallel mesh</td>
+</tr>
+<tr>
+<td>Structured mesh constructs</td>
+<td>S</td>
+<td>BOX_DIMS/I*6, GLOBAL_BOX_DIMS/I*6, BOX_PERIODIC/2*I, __BOX_SET/O</td>
+<td>Data describing structured mesh </td>
+</tr>
+<tr>
+<td>Spectral mesh constructs </td>
+<td>E, S</td>
+<td>SPECTRAL_ORDER/I, SPECTRAL_VERTICES/I*(O+1)^2</td>
+<td>Data marking spectral mesh constructs</td>
+</tr>
+</table>
+ 
+  \ref meta-introduction "Back to Introduction"
+
+  \subsection table2 Table 2: Summary of MOAB conventional tag names, types, and purposes.  Data types are I=integer, D=double, C=character, H=entity handle,O=opaque.  Data type with *x denote length of x elements of that data type.
+
+<Table border="1">
+<tr>
+<th>Tag name</th>
+<th>Data type</th>
+<th>Applies to (E=entity, S=set)</th>
+<th>Purpose</th>
+</tr>
+<tr>
+<td>BOX_DIMS</td>
+<td>I*6</td>
+<td>S</td>
+<td>Lower and upper ijk dimensions of box, ordered (ilo, jlo, klo, ihi, jhi, khi)</td>
+</tr>
+<tr>
+<td>BOX_PERIODIC</td>
+<td>I*2</td>
+<td>S</td>
+<td>Indicates whether box is periodic in i (BOX_PERIODIC[0]) or j (BOX_PERIODIC[1])</td>
+</tr>
+<tr>
+<td>__BOX_SET</td>
+<td>O</td>
+<td>S</td>
+<td>Pointer to corresponding ScdBox instance</td>
+</tr>
+<tr>
+<td>CATEGORY</td>
+<td>C*32</td>
+<td>S</td>
+<td>String describing purpose of set; examples include “group”, “vertex”, “edge”, “surface”, “volume”</td>
+</tr>
+<tr>
+<td>DIRICHLET_SET </td>
+<td>I</td>
+<td>SO</td>
+<td>Entities or sets with common boundary condition</td>
+</tr>
+<tr>
+<td>GEOM_DIMENSION</td>
+<td>I</td>
+<td>S</td>
+<td>Identifies mesh entities resolving a given geometric model entity</td>
+</tr>
+<tr>
+<td>GEOM_SENSE_2</td>
+<td>EH*2</td>
+<td>S</td>
+<td> Stored on face-type geometric topology sets, values store regions having forward and reverse sense</td>
+</tr>
+<tr>
+<td>GEOM_SENSE_N_ENTS</td>
+<td>EH*N</td>
+<td>S</td>
+<td>Stored on edge-type geometric topology sets, values store faces whose senses are stored in GEOM_SENSE_N_SENSES.</td>
+</tr>
+<tr>
+<td>GEOM_SENSE_N_SENSES</td>
+<td>I*N</td>
+<td>S</td>
+<td>Stored on edge-type geometric topology sets, values store senses of the edge with respect to faces stored in GEOM_SENSE_N_ENTS.</td>
+</tr>
+<tr>
+<td>GLOBAL_ID</td>
+<td>I</td>
+<td>E,S</td>
+<td>Application-specific entity id</td>
+</tr>
+<tr>
+<td>MATERIAL_SET</td>
+<td>I</td>
+<td>S</td>
+<td>Entities or sets grouped by material type</td>
+</tr>
+<tr>
+<td>NAME</td>
+<td>C*32</td>
+<td>E, S</td>
+<td>User-assigned entity name(s); multiple names delimited with ?</td>
+</tr>
+<tr>
+<td>NEUMANN_SET</td>
+<td>I</td>
+<td>S</td>
+<td>Entities or sets with common boundary condition </td>
+</tr>
+<tr>
+<td>PARALLEL_PART </td>
+<td>I</td>
+<td>S</td>
+<td>Represent a part in a partition</td>
+</tr>
+<tr>
+<td>PARALLEL_PARTITION</td>
+<td>I</td>
+<td>S</td>
+<td>Represents a partition of the mesh for parallel solution, which is a collection of parts</td>
+</tr>
+<tr>
+<td>__PARALLEL_SHARED_HANDLEd</td>
+<td>H</td>
+<td>E, S</td>
+<td> Handle of this entity/set on sharing processor</td>
+</tr>
+<tr>
+<td>__PARALLEL_SHARED_PROC</td>
+<td>I</td>
+<td>E,S</td>
+<td>Rank of other processor sharing this entity/set </td>
+</tr>
+</table>
+
+\ref meta-data-info "Top"
+
+  \section appendixB Appendix B: CCMIO (Star-CD, Star-CCM+) Reader/Writer Conventions
+
+  \subsection table3 Table 3: Translation between CCMIO options and MOAB tags.
+<Table border="1">
+<tr>
+<th> Set Type</th>
+<th>CCMIO Construct</th>
+<th>MOAB Tag Name, Type</th>
+</tr>
+<tr>
+<td rowspan="2">File set / Interface</td>
+<td>Title (option)</td>
+<td>“Title” (C*32)</td>
+</tr>
+<tr>
+<td>CreatingProgram</td>
+<td>“CreatingProgram” (C*32)</td>
+</tr>
+<tr>
+<td rowspan="13">Material sets</td>
+<td>Index</td>
+<td>MATERIAL_SET</td>
+</tr>
+<tr>
+<td>Label<sup>1</sup></td>
+<td>NAME</td>
+</tr>
+<tr>
+<td>MaterialId</td>
+<td>“MaterialId” (I)</td>
+</tr>
+<tr>
+<td>Radiation</td>
+<td>“Radiation” (I)</td>
+</tr>
+<tr>
+<td>PorosityId</td>
+<td>“PorosityId” (I)</td>
+</tr>
+<tr>
+<td>SpinId</td>
+<td>“SpinId” (I)</td>
+</tr>
+<tr>
+<td>GroupId</td>
+<td>“GroupId” (I)</td>
+</tr>
+<tr>
+<td>ColorIdx</td>
+<td>“ColorIdx” (I)</td>
+</tr>
+<tr>
+<td>ProcessorId</td>
+<td>“ProcessorId” (I)</td>
+</tr>
+<tr>
+<td>LightMaterial</td>
+<td>“LightMaterial” (I)</td>
+</tr>
+<tr>
+<td>FreeSurfaceMaterial</td>
+<td>“Thickness” (F)</td>
+</tr>
+<tr>
+<td>Thickness</td>
+<td>“Thickness” (F)</td>
+</tr>
+<tr>
+<td>MaterialType</td>
+<td>“MaterialType” (C*32)</td>
+</tr>
+<tr>
+<td rowspan="5">Neumann sets</td>
+<td>Index</td>
+<td>NEUMANN_SET</td>
+</tr>
+<tr>
+<td>Label</td>
+<td>NEUMANN_SET</td>
+</tr>
+<tr>
+<td>BoundaryName</td>
+<td>NAME</td>
+</tr>
+<tr>
+<td>BoundaryType</td>
+<td>“BoundaryType” (C*32)</td>
+</tr>
+<tr>
+<td>ProstarRegionNumber</td>
+<td>“ProstarRegionNumber” (I)</td>
+</tr>
+</table>
+
+Notes:
+1. If no name is present, labels the material group with “MaterialX”, where X is the index of that group.
+
+\ref meta-data-info "Top"
+
+  \section appendixC Appendix C: ExodusII Reader/Writer Conventions 
+
+  \subsection table4 Table 4: Translation between ExodusII constructs and MOAB tags.
+<Table border="1">
+<tr>
+<th> Data Type</th>
+<th>ExodusII Construct</th>
+<th>MOAB Tag Name, Type</th>
+</tr>
+<tr>
+<td></td>
+<td>QA records</td>
+<td>“qaRecord” (C*(v))<sup>2</sup></td>
+</tr>
+<tr>
+<td rowspan="2">Material sets</td>
+<td>Block number</td>
+<td>MATERIAL_SET</td>
+</tr>
+<tr>
+<td>Block element type</td>
+<td>Entity type, # vertices per entity</td>
+</tr>
+<tr>
+<td rowspan="2">Dirichlet sets<sup>3</sup></td>
+<td>Nodeset number</td>
+<td>DIRICHLET_SET</td>
+</tr>
+<tr>
+<td>Distribution factors</td>
+<td>“distFactor” (D*(v))<sup>1</sup></td>
+</tr>
+<tr>
+<td>Neumann sets</td>
+<td>Sideset number</td>
+<td>NEUMANN_SET</td>
+</tr>
+<tr>
+<td rowspan="2">Neumann sets, reverse faces3<sup>3</sup></td>
+<td>Distribution factors</td>
+<td>“distFactor” (D*(v))<sup>1</sup></td>
+</tr>
+<tr>
+<td>Sides</td>
+<td>SENSE</td>
+</tr>
+<tr>
+<td>Nodes, elements</td>
+<td>node_num_map, elem_map</td>
+<td>GLOBAL_ID on nodes/elements</td>
+</tr>
+</table>
+
+Notes:
+-# Variable-length tag used for distribution factors; length for each set is the number of entities in
+each set, such that there is one distribution factor for each entity in the set.
+-# QA records are stored as variable-length tags on file set specified on read. Tag is a
+concatenation of QA record strings into a single string, with '\0' used to delimit lines.
+-# MOAB represents sidesets as sets of faces, rather than as sides of elements. Faces can be
+ordered “forward” or “reverse” with respect to one of the bounding elements, depending on
+whether the right-hand normal points into or out of the element. Forward-sense faces are added
+to the Neumann set. Reverse-sense faces are put into a separate set; that set is tagged with the SENSE tag, with value = -1; and that reverse set is added to the Neummann set.
+.
+
+  \ref meta-data-info "Top"
+
+  \section appendixD Appendix D: NC (Climate Data) Reader/Writer Conventions
+
+The climate data reader in MOAB reads files with the '.nc' filename extension. By default, this reader
+reads the whole mesh in the file and creates it as structured mesh in MOAB, with the mesh accessible
+through MOAB's structured mesh interface. By default, all variables and timesteps are read from the
+file, and written as tags on the mesh vertices from that file. This behavior is controlled by the
+“variable”, “nomesh”, “timestep”, and “timeval” options described earlier in this document. If MOAB
+is compiled for parallel execution and configured with a pnetcdf reader, the mesh is read in parallel,
+with a 1D or 2D decomposition designed to balance read performance and communication interface
+size (for details on the partitioning method used, see the src/io/ReadNC.cpp source file).
+
+Mesh is put into the entity set provided to the load_file function. This entity set is also annotated with
+various tags representing information read from the file. These tags are described in Table 5.
+
+Several other things to note about reading climate data files into MOAB:
+- Time-dependent variables: MOAB currently has no mechanism for time-dependent tags. Therefore, time-dependent variables are represented using one tag per timestep, with the tag name set as the variable name plus the timestep index. Thus, the first few timesteps for the variable TEMPERATURE would be represented in tags named TEMPERATURE0, TEMPERATURE1, etc.
+- Cell- and face-centered variables: The climate data reader currently does not do cell- and face-
+centered variables correctly.
+.
+  \subsection table5 Table 5: Summary of MOAB conventional tag names, types, and purposes. Data types are I=integer, D=double, C=character, H=entity handle. Data type with *x denote length of x elements of that data type; data type with *var denote variable-length tag. Tag names with two underscores prepended (“__”) denote tags not written to a file by MOAB.
+
+<Table border="1">
+<tr>
+<th> Tag name </th>
+<th>Data type </th>
+<th> Applies to (E=entity, S=set) </th>
+<th>Purpose </th>
+</tr>
+<tr>
+<td>__NUM_DIMS </td>
+<td>I</td>
+<td>S</td>
+<td>The number of dimensions in the netcdf file.</td>
+</tr>
+<tr>
+<td>__NUM_VARS</td> 
+<td>I</td>
+<td>S</td>
+<td>The number of variables in the netcdf file.</td>
+</tr>
+<tr>
+<td>__DIM_NAMES </td>
+<td>C*var </td>
+<td>S </td>
+<td>The dimension names, concatenated into a
+character string, with '\0' terminating each name.
+ </td>
+</tr>
+<tr>
+<td>__DIM_NAMES 
+</td>
+<td>C*var</td>
+<td>S</td>
+<td>The variable names, concatenated into a character
+string, with '\0' terminating each name.
+</td>
+</tr>
+<tr>
+<td><dim_name> 
+</td>
+<td>(I or 
+D)*va 
+</td>
+<td>S</td>
+<td>For each dimension, the values for the dimension.
+The data type for this tag corresponds to that in the
+netcdf file. The length of this tag is the number of
+values stored for the dimension in the netcdf file.</td>
+</tr>
+<tr>
+<td>__<dim_name>_LOC_MIN MAX</td> 
+<td>2*(I or D)</td>
+<td>S</td>
+<td>The indices (0-based) of the local min and max
+values of dimension stored locally. For spatial
+dimensions like lon or lat, this will store the
+minimum and maximum indices in the loca</td>
+</tr>
+<tr>
+<td >__<dim_name>_LOC_VAL </td> 
+<td>(I or D)*var </td>
+<td>S</td>
+<td>The indices (0-based) of the dimension stored
+locally. This tag only makes sense for dimensions
+that can be read in multiple pieces, such as time.
+Only one of __<dim_name>_LOC_VALS and
+_LOC_MIN_MAX can be used for a given
+dimension.
+</tr>
+<tr>
+<td>__<var_name>_DIMS 
+</td>
+<td>C*n 
+</td>
+<td>S</td>
+<td>For each variable, the tag handles for the
+dimensions defining this variable, in netcdf
+ordering (last dimension varying fastest). The
+length of this tag, n, is # dimensions for the
+variable * sizeof(TagHandle).
+</td>
+</tr>
+<tr>
+<td><var_name><timestep_ind> 
+</td>
+<td>(data type)</td>
+<td>E</td>
+<td>Values of the variable for timestep <timestep_ind>
+for vertices. The data type of this tag corresponds
+to that of the variable from the netcdf file.
+Timestep index is 0-based.
+</td>
+</tr>
+<tr>
+<td>__GLOBAL_ATTRIBS 
+</td>
+<td>C*Var 
+</td>
+<td>S</td>
+<td>The global attributes, concatenated into a character
+string, with ‘\0’ terminating each attribute name, ‘;’
+       separating the data type and value, and ‘;’
+          separating one name/data type/value from the next.
+</td>
+</tr>
+<tr>
+<td>__GLOBAL_ATTRIBS_LEN 
+</td>
+<td>I*Var 
+</td>
+<td>S</td>
+<td>A vector of integers, marking the end position of
+each attribute (name/data type/value) in __GLOBAL_ATTRIBS tag.
+</td>
+</tr>
+<tr>
+<td>__<var_name>_ATTRIBS 
+</td>
+<td>C*Var
+</td>
+<td>S</td>
+<td>The variable attributes, concatenated into a
+character string, with ‘\0’ terminating each attribute
+   name, ‘;’ separating the data type and value, and ‘;’
+          separating one name/data type/value from the next.
+</td>
+</tr>
+<tr>
+<td>__<var_name>_ATTRIBS_LEN 
+</td>
+<td>I*Var
+</td>
+<td>S</td>
+<td>A vector of integers, marking the end position of
+each attribute (name/data type/value) in
+__<var_name>_ATTRIBS tags
+</td>
+</tr>
+</table>
+
+  \ref meta-data-info "Top"
+
+  \section appendixE Appendix E: Nek5000 Reader/Writer Conventions
+
+Nek5000, or Nek, is a code that uses the spectral element method to model fluid, heat transfer,
+electromagnetics, and other physics. Nek uses unstructured hexahedral meshes, with each hex element
+resolved by a structured grid of “Gauss Lebato Legendre” (GLL) points. Nek can read meshes through
+MOAB, and can output physics variables and GLL points through MOAB as well.
+
+Since fluid is a single material in Nek, no material sets are needed. Boundary conditions are mapped to
+Nek's cbc array using Neumann sets and a user-provided “usr_moab2nek” subroutine (for an example
+of this subroutine, see examples/moab/pipe.usr in the Nek source code). GLL point locations and fluid
+variables on those points are stored in tags on the hex elements. All hex elements have the same
+number of GLL points. The number of GLL points in each direction is stored in a tag on the mesh
+instance. These tags are described in Table 6.
+
+GLL point locations and fluid variables are stored in lexicographic order, similar to their storage order
+inside the Nek code.
+
+  \subsection table6 Table 6: Summary of MOAB conventional tag names, types, and purposes for Nek. Data types are I=integer, D=double, C=character, H=entity handle. Data type with *x denote length of x elements of that data type; data type with *var denote variable-length tag. Tag names with two underscores prepended (“__”) denote tags not written to a file by MOAB.
+<Table border="1">
+<tr>
+<th> Tag name </th>
+<th> Data Type</th>
+<th>Applies to (E=entity, S=set)</th>
+<th>Purpose</th>
+</tr>
+<tr>
+<td>SEM_DIMS</td>
+<td>I*3</td>
+<td>S</td>
+<td>The dimensions of the GLL mesh in each hex
+element.
+</td>
+</tr>
+<tr>
+<td>SEM_X</td>
+<td>D*nx*ny*nz</td>
+<td>E</td>
+<td>X position of GLL points (having nx*ny*nz
+values)
+</td>
+</tr>
+<tr>
+<td>SEM_Y</td>
+<td>D*nx*ny*nz</td>
+<td>E</td>
+<td>Y position of GLL points (having nx*ny*nz values)</td>
+</tr>
+<tr>
+<td>SEM_Z</td>
+<td>D*nx*ny*nz</td>
+<td>E</td>
+<td>Z position of GLL points (having nx*ny*nz values)</td>
+</tr>
+<tr>
+<td>VEL_X</td>
+<td>D*nx*ny*nz</td>
+<td>E</td>
+<td>Fluid velocities in the x direction for GLL point
+array (having nx*ny*nz values)</td>
+</tr>
+<tr>
+<td>VEL_Y</td>
+<td>D*nx*ny*nz</td>
+<td>E</td>
+<td>Fluid velocities in the y direction for GLL point
+array (having nx*ny*nz values)</td>
+</tr>
+<tr>
+<td>VEL_Z</td>
+<td>D*nx*ny*nz</td>
+<td>E</td>
+<td>Fluid velocities in the z direction for GLL point
+array (having nx*ny*nz values)</td>
+</tr>
+<tr>
+<td>TEMP</td>
+<td>D*nx*ny*nz</td>
+<td>E</td>
+<td>Fluid temperature for GLL point array (having
+nx*ny*nz values)
+</td>
+</tr>
+<tr>
+<td>PRESS</td>
+<td>D*nx*ny*nz</td>
+<td>E</td>
+<td>Fluid pressure for GLL point array (having
+nx*ny*nz values)
+</td>
+</tr>
+</table>
+  \ref meta-data-info "Top"
+	*/

This diff is so big that we needed to truncate the remainder.

https://bitbucket.org/fathomteam/moab/commits/df9a2ccafd97/
Changeset:   df9a2ccafd97
Branch:      None
User:        tautges
Date:        2013-09-11 20:39:24
Summary:     Changing name of topological_connectivity arguments to various functions to corners_only;
old name always confused me.

Affected #:  3 files

diff --git a/src/Core.cpp b/src/Core.cpp
index faba0f3..25e7ffb 100644
--- a/src/Core.cpp
+++ b/src/Core.cpp
@@ -1138,11 +1138,11 @@ ErrorCode Core::get_connectivity_by_type(const EntityType type,
 ErrorCode  Core::get_connectivity(const EntityHandle *entity_handles,
                                       const int num_handles,
                                       Range &connectivity,
-                                      bool topological_connectivity) const
+                                      bool corners_only) const
 {
   std::vector<EntityHandle> tmp_connect;
   ErrorCode result = get_connectivity(entity_handles, num_handles, tmp_connect,
-                                        topological_connectivity);
+                                        corners_only);
   if (MB_SUCCESS != result) return result;
 
   std::sort( tmp_connect.begin(), tmp_connect.end() );
@@ -1154,7 +1154,7 @@ ErrorCode  Core::get_connectivity(const EntityHandle *entity_handles,
 ErrorCode  Core::get_connectivity(const EntityHandle *entity_handles,
                                   const int num_handles,
                                   std::vector<EntityHandle> &connectivity,
-                                  bool topological_connectivity,
+                                  bool corners_only,
                                   std::vector<int> *offsets) const
 {
   connectivity.clear(); // this seems wrong as compared to other API functions,
@@ -1167,7 +1167,7 @@ ErrorCode  Core::get_connectivity(const EntityHandle *entity_handles,
   int len;
   if (offsets) offsets->push_back(0);
   for (int i = 0; i < num_handles; ++i) {
-    rval = get_connectivity( entity_handles[i], conn, len, topological_connectivity, &tmp_storage );
+    rval = get_connectivity( entity_handles[i], conn, len, corners_only, &tmp_storage );
     if (MB_SUCCESS != rval)
       return rval;
     connectivity.insert( connectivity.end(), conn, conn + len );
@@ -1180,7 +1180,7 @@ ErrorCode  Core::get_connectivity(const EntityHandle *entity_handles,
 ErrorCode Core::get_connectivity(const EntityHandle entity_handle,
                                      const EntityHandle*& connectivity,
                                      int& number_nodes,
-                                     bool topological_connectivity,
+                                     bool corners_only,
                                      std::vector<EntityHandle>* storage) const
 {
   ErrorCode status;
@@ -1207,7 +1207,7 @@ ErrorCode Core::get_connectivity(const EntityHandle entity_handle,
   return static_cast<const ElementSequence*>(seq)->get_connectivity(entity_handle,
                                                               connectivity,
                                                               number_nodes,
-                                                              topological_connectivity,
+                                                              corners_only,
                                                               storage);
 }
 

diff --git a/src/moab/Core.hpp b/src/moab/Core.hpp
index c633321..09c0b13 100644
--- a/src/moab/Core.hpp
+++ b/src/moab/Core.hpp
@@ -221,7 +221,7 @@ public:
           \param entity_handle EntityHandle to get connectivity of.
           \param connectivity Vector in which connectivity of <em>entity_handle</em> is returned.  
           Should contain MeshVertices.
-          \param topological_connectivity If true, higher order nodes are ignored. 
+          \param corners_only If true, returns only corner vertices, otherwise returns all of them (including any higher-order vertices)
 
           Example: \code 
           std::vector<EntityHandle> conn;
@@ -229,7 +229,7 @@ public:
     virtual ErrorCode  get_connectivity(const EntityHandle *entity_handles, 
                                         const int num_handles,
                                         std::vector<EntityHandle> &connectivity, 
-                                        bool topological_connectivity = false,
+                                        bool corners_only = false,
                                         std::vector<int> *offsets = NULL) const;
  
     //! Gets the connectivity for a vector of elements
@@ -238,14 +238,14 @@ public:
   virtual ErrorCode  get_connectivity(const EntityHandle *entity_handles, 
                                         const int num_handles,
                                         Range &connectivity, 
-                                        bool topological_connectivity = false) const;
+                                        bool corners_only = false) const;
 
     //! Gets the connectivity for elements
     /** Same as vector-based version except range is returned (unordered!)
     */
   virtual ErrorCode get_connectivity( const Range& entity_handles, 
                                         Range &connectivity, 
-                                        bool topological_connectivity = false) const;
+                                        bool corners_only = false) const;
  
     //! Gets a pointer to constant connectivity data of <em>entity_handle</em> 
       /** Sets <em>number_nodes</em> equal to the number of nodes of the <em> 
@@ -273,7 +273,7 @@ public:
     virtual ErrorCode  get_connectivity( const EntityHandle entity_handle, 
                                            const EntityHandle *&connectivity, 
                                            int &num_nodes, 
-                                           bool topological_connectivity = false,
+                                           bool corners_only = false,
                                            std::vector<EntityHandle>* storage = 0
                                           ) const;
 

diff --git a/src/moab/Interface.hpp b/src/moab/Interface.hpp
index d7ad8aa..39b12e0 100644
--- a/src/moab/Interface.hpp
+++ b/src/moab/Interface.hpp
@@ -502,14 +502,14 @@ public:
   virtual ErrorCode  get_connectivity(const EntityHandle *entity_handles, 
                                         const int num_handles,
                                         Range &connectivity, 
-                                        bool topological_connectivity = false) const =0;
+                                        bool corners_only = false) const =0;
 
     //! Gets the connectivity for elements
     /** Same as vector-based version except range is returned (unordered!)
     */
   virtual ErrorCode get_connectivity( const Range& entity_handles, 
                                         Range &connectivity, 
-                                        bool topological_connectivity = false) const =0;
+                                        bool corners_only = false) const =0;
  
     //! Gets the connectivity for a vector of elements
     /** Corner vertices or all vertices (including higher-order nodes, if any) are returned.
@@ -520,14 +520,14 @@ public:
         \param entity_handles Vector of element handles to get connectivity of.
         \param num_handles Number of entity handles in <em>entity_handles</em>
         \param connectivity Vector in which connectivity of <em>entity_handles</em> is returned.  
-        \param topological_connectivity If true, higher order nodes are ignored. 
+        \param corners_only If true, returns only corner vertices, otherwise returns all of them (including any higher-order vertices)
         \param offsets If non-NULL, offsets->[i] stores the index of the start of entity i's connectivity,
                 with the last value in offsets one beyond the last entry
     */
   virtual ErrorCode  get_connectivity(const EntityHandle *entity_handles, 
                                       const int num_handles,
                                       std::vector<EntityHandle> &connectivity, 
-                                      bool topological_connectivity = false,
+                                      bool corners_only = false,
                                       std::vector<int> *offsets = NULL) const =0;
  
     //! Gets a pointer to constant connectivity data of <em>entity_handle</em> 
@@ -554,8 +554,7 @@ public:
         \param entity_handle EntityHandle to get connectivity of.
         \param connectivity Array in which connectivity of <em>entity_handle</em> is returned.
         \param num_nodes Number of MeshVertices in array <em>connectivity</em>. 
-        \param topological_connectivity If true, num_nodes will be set to number of corner vertices
-        for that element type.
+        \param corners_only If true, returns only corner vertices, otherwise returns all of them (including any higher-order vertices)
         \param storage Some elements (e.g. structured mesh) may not have an
                        explicit connectivity list.  This function will normally
                        return MB_NOT_IMPLEMENTED for such elements.  However,
@@ -567,7 +566,7 @@ public:
   virtual ErrorCode  get_connectivity(const EntityHandle entity_handle, 
                                         const EntityHandle *&connectivity, 
                                         int &num_nodes, 
-                                        bool topological_connectivity = false,
+                                        bool corners_only = false,
                                         std::vector<EntityHandle>* storage = 0
                                         ) const =0;
 


https://bitbucket.org/fathomteam/moab/commits/32ce13cc7fe5/
Changeset:   32ce13cc7fe5
Branch:      None
User:        tautges
Date:        2013-09-11 21:17:15
Summary:     Merge branch 'master' of https://bitbucket.org/fathomteam/moab

Conflicts:
	.gitignore
	src/AdaptiveKDTree.cpp
	src/io/ReadNC.cpp
	src/moab/point_locater/element_maps/linear_hex_map.hpp
	src/parallel/gs.cpp

Affected #:  115 files

diff --git a/.gitignore b/.gitignore
index 6d53b03..d3721c3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -165,9 +165,13 @@ test/obb/obb_time
 test/obb/obb_tree_tool
 test/obb_test
 test/oldinc/test_oldinc
+test/read_mpas_nc
 test/parallel/*.h5m
 test/parallel/mbparallelcomm_test
 test/parallel/mhdf_parallel
+test/parallel/mpastrvpart
+test/parallel/par_coupler_test
+test/parallel/par_intx_sph
 test/parallel/parallel_hdf5_test
 test/parallel/parallel_unit_tests
 test/parallel/parallel_write_test
@@ -196,6 +200,7 @@ test/perf/point_location/point_location
 test/range_test
 test/reorder_test
 test/scdseq_test
+test/scd_test_partn
 test/seq_man_test
 test/spatial_locator_test
 test/test_boundbox

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 007d501..6b18435 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,3 +1,9 @@
+# check if we are using MPI - reset compilers accordingly
+if ( MOAB_USE_MPI )
+  SET(CMAKE_CXX_COMPILER ${MPI_CXX_COMPILER})
+  SET(CMAKE_C_COMPILER ${MPI_C_COMPILER})
+endif ( MOAB_USE_MPI )
+
 project( MOAB )
 
   cmake_minimum_required( VERSION 2.4 )

diff --git a/MeshFiles/unittest/125hex.g b/MeshFiles/unittest/125hex.g
index 6cf0433..2042583 100644
Binary files a/MeshFiles/unittest/125hex.g and b/MeshFiles/unittest/125hex.g differ

diff --git a/MeshFiles/unittest/1hex.g b/MeshFiles/unittest/1hex.g
index 3dcd658..0affc6e 100644
Binary files a/MeshFiles/unittest/1hex.g and b/MeshFiles/unittest/1hex.g differ

diff --git a/MeshFiles/unittest/1khex.g b/MeshFiles/unittest/1khex.g
index e6c9417..6b0a8fc 100644
Binary files a/MeshFiles/unittest/1khex.g and b/MeshFiles/unittest/1khex.g differ

diff --git a/MeshFiles/unittest/64bricks_512hex_256part.h5m b/MeshFiles/unittest/64bricks_512hex_256part.h5m
new file mode 100644
index 0000000..d7df13c
Binary files /dev/null and b/MeshFiles/unittest/64bricks_512hex_256part.h5m differ

diff --git a/MeshFiles/unittest/surfrandomtris-4part.h5m b/MeshFiles/unittest/surfrandomtris-4part.h5m
new file mode 100644
index 0000000..1ca984a
Binary files /dev/null and b/MeshFiles/unittest/surfrandomtris-4part.h5m differ

diff --git a/configure.ac b/configure.ac
index 21d5fa6..fd4062a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -450,22 +450,25 @@ AC_SUBST(PNETCDF_LIBS)
 #################################################################################
 #                             Documentation
 #################################################################################
-AC_ARG_ENABLE([doxygen],
-[AC_HELP_STRING([[--enable-doxygen@<:@=DIR@:>@]],[Specify directory where Doxygen program is installed])
-AC_HELP_STRING([--disable-doxygen],[Do not generate API documentation (default)])],
-                        [ENABLE_DOXYGEN="$enableval"],[ENABLE_DOXYGEN=no] )
-if test "x$ENABLE_DOXYGEN" = "xyes"; then
-  AC_PATH_PROG( [DOXYGEN], [doxygen], [no] )
-elif test "x$ENABLE_DOXYGEN" != "xno"; then
-  AC_PATH_PROG( [DOXYGEN], [doxygen], [no], [$ENABLE_DOXYGEN] )
+AC_ARG_ENABLE([docs],
+[AC_HELP_STRING([--enable-docs],[indicate to check for doxygen installation])],
+                        [ENABLE_DOCS=yes],[ENABLE_DOCS=no] )
+AC_ARG_WITH([doxygen],
+[AC_HELP_STRING([--with-doxygen=DIR], [Specify directory where Doxygen program is installed. By default, it is /usr/bin])],
+[WITH_DOXYGEN="$withval"], [WITH_DOXYGEN=no])
+
+if test "x$WITH_DOXYGEN" != "xno"; then
+  AC_PATH_PROGS( [DOXYGEN], [doxygen], [no],[$WITH_DOXYGEN] )
+else
+  AC_PATH_PROGS( [DOXYGEN], [doxygen], [no],[$PATH])
 fi
-if test "x$ENABLE_DOXYGEN" != "xno"; then
+if test "x$ENABLE_DOCS" = "xyes"; then
   if test "x$DOXYGEN" = "xno"; then
     AC_MSG_ERROR("Doxygen executable not found.")
   fi
 fi
 AC_SUBST([DOXYGEN])
-AM_CONDITIONAL([ENABLE_DOXYGEN],[test "x$ENABLE_DOXYGEN" != "xno"])
+AM_CONDITIONAL([ENABLE_DOCS],[test "x$ENABLE_DOCS" != "xno"])
 
 
 ################################################################################
@@ -1143,6 +1146,7 @@ AC_SUBST(CGM_CPPFLAGS)
 AC_SUBST(CGM_LDFLAGS)
 AC_SUBST(CGM_LTFLAGS)
 AC_SUBST(CGM_LIBS)
+AC_SUBST(CGM_DIR)
 
 AM_CONDITIONAL( HAVE_CGM, [test "x$CGM_MISSING" = "xno"] )
 
@@ -1211,7 +1215,6 @@ AC_CONFIG_FILES([Makefile
 		 tools/vtkMOABReaderNew/CMakeLists.txt
                  doc/Makefile
                  doc/user.dox
-                 doc/dev.dox
                  doc/config.tex
                  MeshFiles/Makefile
                  MeshFiles/unittest/Makefile

diff --git a/doc/DG/figure1.jpg b/doc/DG/figure1.jpg
new file mode 100644
index 0000000..e102a97
Binary files /dev/null and b/doc/DG/figure1.jpg differ

diff --git a/doc/DG/figure2.jpg b/doc/DG/figure2.jpg
new file mode 100644
index 0000000..7e8b199
Binary files /dev/null and b/doc/DG/figure2.jpg differ

diff --git a/doc/DG/figure3.jpg b/doc/DG/figure3.jpg
new file mode 100644
index 0000000..8810bfc
Binary files /dev/null and b/doc/DG/figure3.jpg differ

diff --git a/doc/DG/moabDG.h b/doc/DG/moabDG.h
index 1091094..32d7fe1 100644
--- a/doc/DG/moabDG.h
+++ b/doc/DG/moabDG.h
@@ -1,45 +1,22 @@
-/*! \page developerguide Developer's Guide (MOAB 4.6)
- 
-  \subpage dg-contents
- 
-  \subpage dg-figures
-
-  \subpage dg-tables
-*/
-
-/*!  \page dg-contents Table of Contents
-
-  \subpage sequence-info
-
-  \subpage meta-data-info
+/*! \page developerguide Developer's Guide (MOAB 4.6)
+ 
+  \subpage dg-contents
+ 
+  \subpage dg-figures
+
 */
-
-/*!  \page dg-figures List of Figures
-
-    \ref figure1
-
-    \ref figure2
-
-    \ref figure3
+
+/*!  \page dg-figures List of Figures
+
+    \ref figure1
+
+    \ref figure2
+
+    \ref figure3
 */
-
-/*!  \page dg-tables List of Tables
-
-    \ref table1
-
-    \ref table2
-
-    \ref table3
-
-    \ref table4
-
-    \ref table5
-
-    \ref table6
-
-*/
 
-/*!  \page sequence-info Sequence Info
+
+/*!  \page dg-contents Table of Contents
 
   \ref sequence
 
@@ -52,6 +29,10 @@
   \section sequence  EntitySequence & SequenceData 
 
   \subsection figure1 Figure 1: EntitySequences For One SequenceData
+  \image html figure1.jpg
+
+  \ref dg-figures "List of Figures"
+
 The <I>SequenceData</I> class manages as set of arrays of per-entity values. Each
 <I>SequenceData</I> has a start and end handle denoting the block of entities for which
 the arrays contain data. The arrays managed by a <I>SequenceData</I> instance are
@@ -111,7 +92,7 @@ a feature. Sequences for which the corresponding data cannot be used to store
 new entities (e.g. structured mesh discussed in a later section) will return -1 or
 some other invalid value.
 
- \ref sequence-info "Top"
+ \ref dg-contents "Top"
 
   \section manager TypeSequenceManager & SequenceManager 
 
@@ -127,6 +108,9 @@ enforces the following four rules on its contained data:
 .
 
   \subsection figure2 Figure 2: SequenceManager and Related Classes
+  \image html figure2.jpg
+
+  \ref dg-figures "List of Figures"
 
 The first three rules are required for the validity of the data model. The
 fourth rule avoids unnecessary inefficiency. It is implemented by merging such
@@ -175,920 +159,115 @@ such as allocating the correct <I>EntitySequence</I> subtype for a given <I>Enti
 
 <sup>2</sup>Given rule four for the data managed by a <I>TypeSequenceManager</I>, any <I>SequenceData</I> for which all handles are allocated will be referenced by exactly one <I>EntitySequence</I>.
 
-  \ref sequence-info "Top"
-
- \section s-mesh Structured Mesh
-
-Structured mesh storage is implemented using subclasses of <I>SequenceData</I>:
-<I>ScdElementData</I> and <I>ScdVertexData</I>. The <I>StructuredElementSeq</I> class is
-used to access the structured element connectivity. A standard <I>VertexSequence</I>
-instance is used to access the ScdVertexData because the vertex data storage
-is the same as for unstructured mesh.
-
-  \ref sequence-info "Top"
-
-  \section sets Entity Sets
-
-- MeshSetSequence
-
-The <I>MeshSetSequence</I> class is the same as most other subclasses of <I>EntitySequence</I>
-in that it utilizes SequenceData to store its data. A single array in the <I>SequenceData</I>
-is used to store instances of the MeshSet class, one per allocated <I>EntityHandle</I>.
-<I>SequenceData</I> allocates all of its managed arrays using malloc and free as
-simple arrays of bytes. <I>MeshSetSequence</I> does in-place construction and de-
-struction of <I>MeshSet</I> instances within that array. This is similar to what is
-done by <I>std::vector</I> and other container classes that may own more storage
-than is required at a given time for contained objects.
-
-- MeshSet
-
-  \subsection figure3 Figure 3: SequenceManager and Related Classes
-
-The <I>MeshSet</I> class is used to represent a single entity set instance in MOAB.
-The class is optimized to minimize storage (further possible improvements in
-storage size are discussed later.)
-
-Figure 3 shows the memory layout of an instance of the <I>MeshSet</I> class.
-The flags member holds the set creation bit flags: <I>MESHSET_TRACK_OWNER</I>,
-<I>MESHSET_SET</I>, and <I>MESHSET_ORDERED</I>. The presence of the <I>MESHSET_TRACK_OWNER</I>
-indicates that reverse links from the contained entities back to the owning set
-should be maintained in the adjacency list of each entity. The <I>MESHSET_SET</I>
-and <I>MESHSET_ORDERED</I> bits are mutually exclusive, and as such most code only
-tests for the <I>MESHSET_ORDERED</I>, meaning that in practice the <I>MESHSET_SET</I> bit is
-ignored. <I>MESHSET_ORDERED</I> indicates that the set may contain duplicate handles
-and that the order that the handles are added to the set should be preserved.
-In practice, such sets are stored as a simple list of handles. <I>MESHSET_SET</I> (or in
-practice, the lack of <I>MESHSET_ORDERED</I>) indicates that the order of the handles
-need not be preserved and that the set may not contain duplicate handles. Such
-sets are stored in a sorted range-compacted format similar to that of the Range
-class.
-
-The memory for storing contents, parents, and children are each handled in
-the same way. The data in the class is composed of a 2-bit ‘size’ field and two
-values, where the two values may either be two handles or two pointers. The size
-bit-fields are grouped together to reduce the required amount of memory. If the
-numerical value of the 2-bit size field is 0 then the corresponding list is empty.
-If the 2-bit size field is either 1 or 2, then the contents of the corresponding list
-are stored directly in the corresponding two data fields of the MeshSet object.
-If the 2-bit size field has a value of 3 (11 binary), then the corresponding two
-data fields store the begin and end pointers of an external array of handles.
-The number of handles in the external array can be obtained by taking the
-difference of the start and end pointers. Note that unlike <I>std::vector</I>, we
-do not store both an allocated and used size. We store only the ‘used’ size
-and call std::realloc whenever the used size is modified, thus we rely on the
-std::malloc implementation in the standard C library to track ‘allocated’ size
-for us. In practice this performs well but does not return memory to the ‘system’
-when lists shrink (unless they shrink to zero). This overall scheme could exhibit
-poor performance if the size of one of the data lists in the set frequently changes
-between less than two and more than two handles, as this will result in frequent
-releasing and re-allocating of the memory for the corresponding array.
-
-If the <I>MESHSET_ORDERED</I> flag is not present, then the set contents list (parent
-and child lists are unaffected) is stored in a range-compacted format. In this
-format the number of handles stored in the array is always a multiple of two.
-Each consecutive pair of handles indicate the start and end, inclusive, of a range
-of handles contained in the set. All such handle range pairs are stored in sorted
-order and do not overlap. Nor is the end handle of one range ever one less than
-the start handle of the next. All such ‘adjacent’ range pairs are merged into a
-single pair. The code for insertion and removal of handles from range-formatted
-set content lists is fairly complex. The implementation will guarantee that a
-given call to insert entities into a range or remove entities from a range is never
-worse than O(ln n) + O(m + n), where ‘n’ is the number of handles to insert
-and ‘m’ is the number of handles already contained in the set. So it is generally
-much more efficient to build Ranges of handles to insert (and remove) and call
-MOAB to insert (or remove) the entire list at once rather than making may
-calls to insert (or remove) one or a few handles from the contents of a set.
-The set storage could probably be further minimized by allowing up to six
-handles in one of the lists to be elided. That is, as there are six potential ‘slots’
-in the MeshSet object then if two of the lists are empty it should be possible to store up to six values of the remaining list directly in the MeshSet object.
-However, the additional runtime cost of such complexity could easily outweigh
-any storage advantage. Further investigation into this has not been done because
-the primary motivation for the storage optimization was to support binary trees.
-
-Another possible optimization of storage would be to remove the <I>MeshSet</I>
-object entirely and instead store the data in a ‘blocked’ format. The corre-
-sponding <I>SequenceData</I> would contain four arrays: flags, parents, children, and
-contents instead of a single array of <I>MeshSet</I> objects. If this were done then
-no storage need ever be allocated for parent or child links if none of the sets
-in a <I>SequenceData</I> has parent or child links. The effectiveness of the storage
-reduction would depend greatly on how sets get grouped into <I>SequenceDatas</I>.
-This alternate storage scheme might also allow for better cache utilization as it
-would group like data together. It is often the case that application code that
-is querying the contents of one set will query the contents of many but never
-query the parents or children of any set. Or that an application will query only
-parent or child links of a set without every querying other set properties. The
-downside of this solution is that it makes the implementation a little less mod-
-ular and maintainable because the existing logic contained in the <I>MeshSet</I> class
-would need to be spread throughout the <I>MeshSetSequence</I> class.
-
-  \ref sequence-info "Top"
+  \ref dg-contents "Top"
+
+ \section s-mesh Structured Mesh
+
+Structured mesh storage is implemented using subclasses of <I>SequenceData</I>:
+<I>ScdElementData</I> and <I>ScdVertexData</I>. The <I>StructuredElementSeq</I> class is
+used to access the structured element connectivity. A standard <I>VertexSequence</I>
+instance is used to access the ScdVertexData because the vertex data storage
+is the same as for unstructured mesh.
+
+  \ref dg-contents "Top"
+
+  \section sets Entity Sets
+
+- MeshSetSequence
+
+The <I>MeshSetSequence</I> class is the same as most other subclasses of <I>EntitySequence</I>
+in that it utilizes SequenceData to store its data. A single array in the <I>SequenceData</I>
+is used to store instances of the MeshSet class, one per allocated <I>EntityHandle</I>.
+<I>SequenceData</I> allocates all of its managed arrays using malloc and free as
+simple arrays of bytes. <I>MeshSetSequence</I> does in-place construction and de-
+struction of <I>MeshSet</I> instances within that array. This is similar to what is
+done by <I>std::vector</I> and other container classes that may own more storage
+than is required at a given time for contained objects.
+
+- MeshSet
+
+  \subsection figure3 Figure 3: SequenceManager and Related Classes
+  \image html figure3.jpg
+
+  \ref dg-figures "List of Figures"
+
+The <I>MeshSet</I> class is used to represent a single entity set instance in MOAB.
+The class is optimized to minimize storage (further possible improvements in
+storage size are discussed later.)
+
+Figure 3 shows the memory layout of an instance of the <I>MeshSet</I> class.
+The flags member holds the set creation bit flags: <I>MESHSET_TRACK_OWNER</I>,
+<I>MESHSET_SET</I>, and <I>MESHSET_ORDERED</I>. The presence of the <I>MESHSET_TRACK_OWNER</I>
+indicates that reverse links from the contained entities back to the owning set
+should be maintained in the adjacency list of each entity. The <I>MESHSET_SET</I>
+and <I>MESHSET_ORDERED</I> bits are mutually exclusive, and as such most code only
+tests for the <I>MESHSET_ORDERED</I>, meaning that in practice the <I>MESHSET_SET</I> bit is
+ignored. <I>MESHSET_ORDERED</I> indicates that the set may contain duplicate handles
+and that the order that the handles are added to the set should be preserved.
+In practice, such sets are stored as a simple list of handles. <I>MESHSET_SET</I> (or in
+practice, the lack of <I>MESHSET_ORDERED</I>) indicates that the order of the handles
+need not be preserved and that the set may not contain duplicate handles. Such
+sets are stored in a sorted range-compacted format similar to that of the Range
+class.
+
+The memory for storing contents, parents, and children are each handled in
+the same way. The data in the class is composed of a 2-bit ‘size’ field and two
+values, where the two values may either be two handles or two pointers. The size
+bit-fields are grouped together to reduce the required amount of memory. If the
+numerical value of the 2-bit size field is 0 then the corresponding list is empty.
+If the 2-bit size field is either 1 or 2, then the contents of the corresponding list
+are stored directly in the corresponding two data fields of the MeshSet object.
+If the 2-bit size field has a value of 3 (11 binary), then the corresponding two
+data fields store the begin and end pointers of an external array of handles.
+The number of handles in the external array can be obtained by taking the
+difference of the start and end pointers. Note that unlike <I>std::vector</I>, we
+do not store both an allocated and used size. We store only the ‘used’ size
+and call std::realloc whenever the used size is modified, thus we rely on the
+std::malloc implementation in the standard C library to track ‘allocated’ size
+for us. In practice this performs well but does not return memory to the ‘system’
+when lists shrink (unless they shrink to zero). This overall scheme could exhibit
+poor performance if the size of one of the data lists in the set frequently changes
+between less than two and more than two handles, as this will result in frequent
+releasing and re-allocating of the memory for the corresponding array.
+
+If the <I>MESHSET_ORDERED</I> flag is not present, then the set contents list (parent
+and child lists are unaffected) is stored in a range-compacted format. In this
+format the number of handles stored in the array is always a multiple of two.
+Each consecutive pair of handles indicate the start and end, inclusive, of a range
+of handles contained in the set. All such handle range pairs are stored in sorted
+order and do not overlap. Nor is the end handle of one range ever one less than
+the start handle of the next. All such ‘adjacent’ range pairs are merged into a
+single pair. The code for insertion and removal of handles from range-formatted
+set content lists is fairly complex. The implementation will guarantee that a
+given call to insert entities into a range or remove entities from a range is never
+worse than O(ln n) + O(m + n), where ‘n’ is the number of handles to insert
+and ‘m’ is the number of handles already contained in the set. So it is generally
+much more efficient to build Ranges of handles to insert (and remove) and call
+MOAB to insert (or remove) the entire list at once rather than making may
+calls to insert (or remove) one or a few handles from the contents of a set.
+The set storage could probably be further minimized by allowing up to six
+handles in one of the lists to be elided. That is, as there are six potential ‘slots’
+in the MeshSet object then if two of the lists are empty it should be possible to store up to six values of the remaining list directly in the MeshSet object.
+However, the additional runtime cost of such complexity could easily outweigh
+any storage advantage. Further investigation into this has not been done because
+the primary motivation for the storage optimization was to support binary trees.
+
+Another possible optimization of storage would be to remove the <I>MeshSet</I>
+object entirely and instead store the data in a ‘blocked’ format. The corre-
+sponding <I>SequenceData</I> would contain four arrays: flags, parents, children, and
+contents instead of a single array of <I>MeshSet</I> objects. If this were done then
+no storage need ever be allocated for parent or child links if none of the sets
+in a <I>SequenceData</I> has parent or child links. The effectiveness of the storage
+reduction would depend greatly on how sets get grouped into <I>SequenceDatas</I>.
+This alternate storage scheme might also allow for better cache utilization as it
+would group like data together. It is often the case that application code that
+is querying the contents of one set will query the contents of many but never
+query the parents or children of any set. Or that an application will query only
+parent or child links of a set without every querying other set properties. The
+downside of this solution is that it makes the implementation a little less mod-
+ular and maintainable because the existing logic contained in the <I>MeshSet</I> class
+would need to be spread throughout the <I>MeshSetSequence</I> class.
+
+  \ref dg-contents "Top"
 */
-
-/*! \page meta-data-info I/O and Meta-Data Storage Conventions in MOAB
-
-  <Center><H3> Timothy J. Tautges </H3></Center>
-
-    \ref meta-introduction
-
-    \ref meta-conventions
-
-    \ref meta-options
-
-    \ref meta-references
-
-    \ref appendixA
-
-    \ref appendixB
-
-    \ref appendixC
-
-    \ref appendixD
-
-    \ref appendixE
-
-  \section meta-introduction  Introduction
-
-The Mesh-Oriented datABase (MOAB) is a library for representing finite element and other types of mesh data [1].  Various types of meta-data are often used in conjunction with a mesh.  Examples include boundary condition groupings, material types, and provenance information for the mesh.  Because the data model used in MOAB is so abstract, conventions are useful for describing how meta-data is stored into that data model.  This document describes those conventions for several types of data commonly found in meshes stored in MOAB.  Because the data models used by MOAB and iMesh, the ITAPS mesh interface [2], are so similar, the conventions described here apply almost unmodified to iMesh as well as to MOAB.
-
-The meshes represented in MOAB originate in a variety of forms, including mesh read from files of various formats (e.g. CUBIT “.cub” file, VTK, etc.) as well as mesh written into MOAB directly by various software libraries (e.g. MeshKit).  Although there is no standard for naming or storing meta-data with a mesh, there is a great deal of commonality in the types of meta-data typically found with mesh data.  This document describes conventions that have been established for commonly encountered meta-data.  Various mesh readers implemented in MOAB attempt to read meta-data from a file and write it into the MOAB data model using these conventions.  Although there is no requirement to store a given type of meta-data in the form described here, a number of services have been written to handle meta-data using these conventions, no matter the source of the meta-data being processed.
-
-Several specific tools are often used in concert with MOAB and bear special mention here.  The CUBIT toolkit generates finite element meshes, and saves them to a native save file (referred to as a “.cub” file) which MOAB is able to read.  Reading CUBIT meshes into MOAB through the .cub file format is preferred over other formats, since most other mesh formats written by CUBIT do not save most meta-data.  The MeshKit library also generates mesh using CGM and MOAB, and uses the same conventions for storing meshes into MOAB.  Finally, MOAB includes a CGM reader which can read a geometric model into a faceted representation in MOAB.  Meta-data from all these tools are stored in MOAB using the conventions described here. 
-
-The MOAB data model consists of the following basic types:
-- <B>Entity</B>: The basic elements of topology, e.g. vertex, edge, triangle, tetrahedron, etc.  MOAB represents all types in the finite element zoo, plus polygons and polyhedra.
-- <B>Entity Set</B>: An arbitrary collection of entities and other sets.  Sets can have parent/child relations with other sets, and these relations are distinct from “contains” relations.
-- <B>Interface</B>: The interface object through which other entities are accessed, in the sense of object-oriented-programming.  iMesh refers to the interface as the “root” set.
-- <B>Tag</B>: A piece of data that can be assigned a distinct value to each entity and entity set, and to the interface itself.  Tags have a prescribed name, size in bytes, and data type; allowed data types are integer, double, entity handle, and byte or opaque.
-.
-
-The following section describes each meta-data tag convention in detail; these conventions are also summarized in Table 1.
-
-  \ref meta-data-info "Top"
-
-  \section meta-conventions  Meta-Data Conventions
-
-Meta-data is stored in MOAB and iMesh in the form of tags applied to either entities or entity sets.  For meta-data represented as entity sets, the contents of those sets are determined by the convention, with tags on those sets identifying them with the convention and adding any other semantic data.
-
-Each meta-data convention is described in a subsection below.  Each convention begins with a short description of:
-- Whether tags associated with the convention are assigned to entities or entity sets
-- The tag(s) associated with the convention; information for each tag includes the name, the data type (I=integer, D=double, C=character, H=handle), and the tag length.  Tag lengths are specified after an asterisk (*); for example, C*32 implies a tag with character type and length 32.  Unspecified lengths correspond to length one.
-.
-
-<H3>Name</H3>
-
-(Data: Entity sets, entities; Tag(s): NAME/C*32)
-
-Character strings are used in many different contexts in applications.  MOAB uses the “NAME” tag to store character strings used to name entities.  This tag is of byte-type and is of length 32 bytes.  Note that the string stored in this tag may or may not be terminated with a NULL character.  It is always prudent account for missing NULL terminator, to avoid buffer overflow errors in the application.  Applications are free to define their own version of the NAME tag with a longer length, though this definition may conflict with other services attempting to use this tag with the conventional size.  Applications needing a string tag with a longer or variable length can also use MOAB’s variable-length tag type, though this will not be compatible with iMesh.
-
-<H3>Title </H3>
-
-(Data: Entity sets (file or instance); Tag(s): TITLE/C*strlen)
-
-The title tag is meant to hold the overall identifier of a mesh, written at generation time or read from a file generated with a non-MOAB tool.  The tag length is variable, and is set by the application directly (by calling the tag_create function) or indirectly (by embedding the title in a file read by MOAB).
-
-<H3> Global Identifier </H3>
-
-(Data: Entity sets, entities; Tag(s): GLOBAL_ID/I)
-
-Global identifiers are used in many different contexts in applications.  Geometric model entities are identified by dimension and id, e.g. “Volume 1”.  Mesh vertices and elements are identified similarly in mesh generation codes.  Boundary conditions and material types are identified similarly.  This tag is used to store such information.  This tag is currently stored in a 32-byte integer, though this may change in the future.
-
-<H3> Geometric Model Information </H3>
-
-(Data: Entity sets; Tag(s): GEOM_DIMENSION/I, GLOBAL_ID/I, NAME/C*32, CATEGORY/C*32, GEOM_SENSE_2(EH[2]), GEOM_SENSE_N_ENTS(EH*N), GEOM_SENSE_N_SENSES(I*N))
-
-Mesh generation is often performed starting from a geometric model, represented in some form of CAD engine.  Many of the meshes used by MOAB are generated based on the CGM library.  Geometric models contain both topological information (the topological entities in the geometric model) and shape information (the geometric shape of those entities), as well as other meta-data written to the entities in a model.  When a mesh is read from a CUBIT .cub file, meta-data from the geometric model is read and represented in the MOAB data model, as described below. <B> Note that although MOAB reads and represents meta-data associated with the geometric model, it does not represent the geometric model itself.</B>  Therefore, shape-related information, e.g. the arc length of an edge or surface normal at a given point, can be retrieved only from the model represented in CGM or another geometric modeling engine.
-
-The information contained in a geometric model, read into and represented in MOAB, consists of:
-- Model entities (vertex, edge, face, volume)
-- Topological relationships between model entities
-- Groups of model entities
-- Model entity/group ids
-- Model entity/group names
-.
-The storage of this information into MOAB's data model is described for each type is described below.
-
-- <B>Entities </B>
-
-Entities in the geometric model (VERTEX, EDGE, FACE, VOLUME) are each represented by an entity set<sup>1</sup>.  These sets are tagged with the “GEOM_DIMENSION” tag, with integer value equal to the topological dimension of the entity (VERTEX = 0, EDGE = 1, etc.)  These sets contain the mesh owned by the corresponding entity in the geometric model.  Note this does not include mesh owned by bounding entities; thus, the set for a FACE will not contain the mesh vertices owned by bounding EDGEs in the geometric model.  These sets may or may not contain mesh entities of intermediate dimension, e.g. mesh edges owned by a FACE or faces owned by a VOLUME, depending on the application generating the mesh or the file from which the mesh was read.  These sets are all set-types, i.e. the order of entities in the sets is not significant, except in the case of EDGE sets, where order of the mesh vertices and edges corresponds to the relative order of vertices and edges at the time of mesh generation.  In MOAB, these sets are non-tracking by default, i.e. entities do not have knowledge of which geometry sets they are members of.
-
-<sup>1</sup>Body-type entities from CUBIT are not explicitly represented in MOAB.
-
-- <B> Topological Relationships </B>
-
-In the geometric model, each FACE is bounded by zero or more EDGEs; other topological relationships between geometric entities exist in a similar manner.  These relationships are embedded in the data model using parent/child relations between entity sets.  For example, the entity set corresponding to a FACE will have child sets, each corresponding to a bounding EDGE, and parent sets, each corresponding to a VOLUME bounded by that FACE.  The relative order of sets in those parent/child lists is not significant, thus, “loops” bounding a FACE cannot reliably be inferred from this data.
-
-- <B> Groups </B>
-
-Geometric entities are sometimes assigned to application-specific groups.  These groups are represented using entity sets, tagged with a “GROUP” tag whose value equals the group id.  Group sets are “set”-type, and are not tracking sets.  These sets contain the sets corresponding to geometric entities contained in the groups in the geometric model, as well as any mesh entities assigned to the group.
-
-<H4> Sense </H4>
-
-A geometric face has a natural orientation, indicated by the direction of the normal to the face; similarly, edges have a natural orientation determined by the direction of the tangent.  When faces bound regions, or edges bound faces, they do so with a sense; if a region includes a face with forward sense, that means the face's natural normal direction points out of the volume.  If a face includes an edge with forward sense, that means that if one moves along the edge in the direction of its tangent, the material of the face is on the left hand side.  The sense of a face (edge) with respect to a region (face) it bounds is stored using tags on the face (edge).
-
-Most models allow a face to be part of only two regions.  Therefore, to store the sense of a face with respect to regions including it, a tag with two values is used.  This tag is named GEOM_SENSE_2, and has 2 EntityHandle values.  The first value corresponds to the entity set for the region for which that face has a forward sense, and the second to the region for which that face has a reverse sense.
-
-Edges can bound more than two faces.  Therefore, two variable-length tags are used, one to store the EntityHandles of the faces the edge bounds, and the other to store the sense with which the edge bounds the corresponding face.  These tags are named GEOM_SENSE_N_ENTS and GEOM_SENSE_N_SENSES, respectively.  These are stored as variable-length tags; see the MOAB user's guide for information on how to work with tags of this type. 
-
-The following sense values are used:
-- 0: forward
-- 1: reverse
-- -1: unnknown
-
-<H3> Material Type </H3>
-
-(Data: Entity sets; Tag(s): MATERIAL_SET/I)
-
-Most finite element and other PDE-based analysis codes require a material type for each cell or element in the simulation.  MOAB uses entity sets to store this information, in the form of entity sets.  The MATERIAL_SET tag is used to identify these sets.  The value of this tag is conventionally an integer; in most cases this stores a user-assigned identifier associated with that material. 
-
-CUBIT assigns material types using what it calls “element blocks”, with each element block given a user-assigned id number and optionally a name.  The CUBIT and Exodus file readers in MOAB read element blocks into MATERIAL_SET sets.  
-
-In CUBIT, materials are typically assigned by assigning geometric volumes to element blocks.  Therefore, material sets often contain entity sets corresponding to those volumes.  Thus, a materrial set in MOAB is unlikely to contain mesh entities directly; rather, that set contains other sets which contain mesh entities.  In these cases, mesh entities can be retrieved by passing a “recursive” flag to the appropriate function (MOAB), or by calling the getEntitiesRec extension function (iMesh) provided by MOAB.
-
-<H3> Boundary Conditions (Dirichlet, Neumann)</H3>
-
-Data: Entity sets; Tag(s): DIRICHLET_SET/I, NEUMANN_SET/I)
-
-Boundary conditions are often specified in terms of geometric model entities, similar to material types.  MOAB uses entity sets to store this information as well.  The DIRICHLET_SET and NEUMANN_SET tags are used to represent Dirichlet- and Neumann-type boundary condition sets, resp.  By convention, Neumann sets usually contain (indirectly) intermediate-dimension entities like edges in a 2D mesh or faces in a 3D mesh, while Dirichlet sets usually contain vertices.  In addition, Neumann sets are represented as sets of faces, rather than as sides of elements.  Faces can be ordered “forward” or “reverse” with respect to one of the bounding elements, depending on whether the right-hand normal points into or out of the element.  Forward-sense faces are added to the Neumann set.  Reverse-sense faces are put into a separate set; that set is tagged with the NEUSET_SENSE tag, with value = -1; and that reverse set is added to the Neummann set.
-
-<H3> Parallel Mesh Constructs </H3>
-
-(Data: Entity sets, entities; Tag(s): PARALLEL_PART/I, PARALLEL_PARTITION/I, PSTATUS/C*1, PARALLEL_SHARED_PROC/I, PARALLEL/SHARED_HANDLE/H, PARALLEL_SHARED_PROCS/I*NP, PARALLEL_SHARED_HANDLES/H*NP)
-
-On a parallel computer, MOAB can represent the mesh on each processor as well as information about entities shared with neighboring processors.  Some of this information is also relevant even when the mesh is represented on a serial machine.  MOAB uses several tag and set conventions to describe the parallel nature of a mesh.  This information is summarized here; for a more complete description of MOAB’s parallel mesh representation and functionality, see [ref-moabpar].
-
-- <B> Parallel partition, parts </B>
-
-Most parallel mesh applications use a domain decomposition approach, where each processor solves for a subset of the domain.  The set of entities solved by a given processor is referred to as a part, and the collection of parts together is called the partition.  MOAB stores each part in an entity set, marked with the PARALLEL_PART tag, whose value is the rank of the processor assigned that part; an entity set which contains all part sets is given the PARALLEL_PARTITION tag, whose value is currently meaningless.  The MBZoltan tool included as a tool in MOAB can partition a mesh for parallel solution, and writes the partition to the mesh in the form of parts and partitions.  Both these types of sets can be accessed in a serial mesh, e.g. for visualization.
-
-- <B> Part interfaces </B>
-
-When a partitioned mesh has been loaded on a parallel computer, the part on a given processor may share portions of its boundary with parts on other processors.  These shared regions are called part interfaces, and are also represented using entity sets.  These sets are marked with the PARALLEL_INTERFACE tag, whose value is currently meaningless.
-
-- <B> Shared processor and handle </B>
-
-For entities shared between processors, it is helpful to know locally which other processor shares an entity, and what the entity’s handle is on the remote processor.  There are two cases which are useful to distinguish, first where an entity is shared with only one other processor (referred to as shared), and second when a processor is shared by more than one other processor (referred to as multi-shared).   Shared entities are given the PARALLEL_SHARED_PROC and PARALLEL_SHARED_HANDLE tags, which store the rank of the sharing processor and the handle of the entity on that processor, respectively.  Multi-shared entities are marked with the PARALLEL_SHARED_PROCS and PARALLEL_SHARED_HANDLES tags; these tags have a length NP assigned at compile time in MOAB, with default values of -1 for processor rank and zero for handle (which are each invalid values for the corresponding data).  The processors/handles sharing a given entity are then written on the front of the arrays.  So, for example, an entity on processor rank 0, shared by processors 1 and 2, would have a PARALLEL_SHARED_PROCS tag whose values would be [1, 2, -1, -1, …], with PARALLEL_SHARED_HANDLES values of [m, n, 0, 0, …], where m and n would be the handles of that entity on processors 1 and 2.  The shared versions of these tags are “dense”, with default values which denote unshared entities.  The multi-shared tags are sparse tags in MOAB, with no default value.
-
-- <B> Parallel status </B>
-
-In addition to the tags above, MOAB also defines the PSTATUS tag, whose bits contain information about the parallel status of a given entity.  Starting with least significant bit, these bits represent whether an entity is 1) not owned, 2) shared, 3) multi-shared, 4) interface, 5) a ghost entity.  The first bit being set indicates “not owned” so that the default value for this tag, of zero, corresponds to an owned, unshared entity, which will be the state of most entities on a given processor.
-
-<H3>Structured Mesh Parameters </H3>
-
-MOAB has a structured mesh interface for creating structured mesh (see “ScdInterface.hpp” header file in MOAB source code).  Along with an internal representation that is more memory-efficient (since it does not need to store connectivity), MOAB also creates and tags entity sets with structured mesh parameters, which can be accessed through the normal tag and set interface.  The following tags are used:
-- <B>BOX_DIMS</B>: This tag stores the ijk coordinates of the lower and upper corner of the structured mesh box(es).
-- <B>GLOBAL_BOX_DIMS</B>: If specified when the structured mesh is created, a tag with this name stores the global box dimensions (which may be different than the local box dimensions).
-- <B>BOX_PERIODIC</B>: Stores whether the box is periodic in the i (BOX_PERIODIC[0]) and j (BOX_PERIODIC[1]) directions.
-- <B>__BOX_SET</B>: Pointer to the ScdBox instance corresponding to this entity set.<sup>2</sup>
-.
-Although the structured mesh is not saved as such in HDF5-format files, the entity sets and corresponding tags will be saved and restored.
-
-<sup>2</sup>The double-underscore in the tag name implies that this tag will not be saved in a file, in this case because the ScdBox instances are not preserved in a file.
-
-<H3>Spectral Mesh Constructs </H3>
-
-The Spectral Element Method (SEM) is a high-order method, using a polynomial Legendre interpolation basis with Gauss-Lobatto quadrature points, in contrast to the Lagrange basis used in (linear) finite elements.  A spectral mesh with order O contains quadrilateral or hexahedral elements comprised of (O+1)d vertices.  Spectral meshes are usually represented in one of two ways, either as coarse elements which point to an array of higher-order vertices (and with corner vertices represented in the normal manner), or as linear quads/hexes formed from the higher-order vertices, with each original coarse quad/hex represented by Od fine quads/hexes.  Similarly, the spectral variables, which are normally computed at fine vertex positions, are stored either on those vertices, or in lexicographically-ordered arrays on elements (with tag values repeated on neighboring elements).  MOAB can read spectral meshes from a variety of formats (at this time, including CAM-SE, HOMME, and Nek5000).  Which of the above two representations are controlled by read options and are indicated by certain tags:
-- SPECTRAL_MESH: read option indicating that spectral elements should be represented as coarse linear quads/hexes and each element containing an array of lexicographically-ordered vertex handles
-- TAG_SPECTRAL_ELEMENTS: read option; if given, spectral variables are represented as lexicographically-ordered arrays on elements
-- TAG_SPECTRAL_VERTICES: read option; if given, spectral variables are represented as tags on vertices
-- CONN=<filename>: in CAM-SE, the connectivity of the spectral mesh is stored by default in a file named “HommeMapping.nc”; this option can be given to read the connectivity from a different file
-- SPECTRAL_VERTICES: tag name for array of vertex handles
-- SPECTRAL_ORDER: tag name for spectral order, written to file set or (if no file set given) to interface after a spectral mesh is read
-.
-
-  \ref meta-data-info "Top"
-
-  \section meta-options Reader/Writer Options
-
-All mesh file readers and writers in MOAB take an option string as an argument.  By default, the semicolon (“;”) delimits individual options in the option string.  Options used in multiple readers are described in this section; the options enabled in specific readers/writers are described in the corresponding appendix at the end of this document.
-
-<H3>variable=<var_name>[,...]</H3>
-
-By default, all field data stored with the mesh is read with the mesh, and stored as tags on the associated mesh entities.  This option lists specific variables that should be read along with the mesh (note also the “nomesh” option, described elsewhere in this document).  The variable name listed will be read into a tag with the same name.  For time-dependent variables, the time step number will be appended to the variable name to form the tag name.  If no “timestep” or “timeval” option is given, all time steps will be read, resulting in several tags being created.  If the “nomesh” option is given, the application must pass the entity set resulting from the original mesh read in to the function, that this set must contain the mesh read only from that file.  The mesh in the file is checked against the mesh in the set to verify that the two correspond.  The special name “MOAB_ALL_VARIABLES” can be used to indicate that all variables should be read.  Multiple variable names can be specified, separated from each other by commas.
-
-<H3>nomesh </H3>
-
-Indicates that no mesh should be read from the file.  This option is used in conjunction with the “variable=” option, to read variables and assign them as tags to a previously-read mesh.  If this option is used, applications should pass an entity set to the read function, which should contain the mesh previously read from the file.
-
-<H3>timestep=<step_number>[, ...] </H3>
-
-Read the time step number whose time value is equal to or greater than the specified time value, for the specified variable(s).  Tag names for the variable(s) will be formed by appending the time step number to the variable name.  Multiple time step values can be specified, separated from each other by commas.
-
-  \ref meta-data-info "Top"
-
-  \section meta-references References
-
-[1]	T.J. Tautges, R. Meyers, K. Merkley, C. Stimpson, and C. Ernst, MOAB: A Mesh-Oriented Database, Sandia National Laboratories, 2004.
-
-[2]	L. Diachin, A. Bauer, B. Fix, J. Kraftcheck, K. Jansen, X. Luo, M. Miller, C. Ollivier-Gooch, M.S. Shephard, T. Tautges, and H. Trease, “Interoperable mesh and geometry tools for advanced petascale simulations,” Journal of Physics: Conference Series,  vol. 78, 2007, p. 012015.
-
-\ref meta-data-info "Top"
-
-  \section appendixA Appendix A: Summary
-
-  \subsection table1 Table 1: Summary of MOAB meta-data conventions.
-
-<table border="1">
-<tr>
-<th>Convention</th>
-<th>Applies to (E=ent, S=set)</th>
-<th>Tag(s) (type/length)</th>
-<th>Description</th>
-</tr>
-<tr>
-<td>Name</td>
-<td>E, S</td>
-<td>NAME/C*32</td>
-<td></td>
-</tr>
-<tr>
-<td>Title</td>
-<td>S</td>
-<td>TITLE/C*strlen</td>
-<td>Title of mesh</td>
-</tr>
-<tr>
-<td>Global identifier</td>
-<td>E, S</td>
-<td>GLOBAL_ID/I</td>
-<td></td>
-</tr>
-<tr>
-<td>Geometric topology</td>
-<td>S</td>
-<td>GEOM_DIMENSION/I, GLOBAL_ID/I,
-NAME/C*32,
-CATEGORY/C*32.
-GEOM_SENSE_2/EH[2],
-GEOM_SENSE_N_ENTS/EH*N,
-GEOM_SENSE_N_SENSES/I*N</td>
-<td>Sets contain mesh owned by that entity; parent/child links to bounded/bounding entities in geometric model</td>
-</tr>
-<tr>
-<td>Material type</td>
-<td>S</td>
-<td>MATERIAL_SET/I</td>
-<td>Set contains entities or sets assigned a common material type</td>
-</tr>
-<tr>
-<td>Boundary condition</td>
-<td>S</td>
-<td>DIRICHLET_SET/I, NEUMANN_SET/I</td>
-<td>Set contains entities or sets assigned a particular boundary condition; neumann sets usually contain edges (2D) or faces (3D)</td>
-</tr>
-<tr>
-<td>Parallel mesh constructs</td>
-<td>E, S</td>
-<td>PARALLEL_PART/I, PARALLEL_PARTITION/I, PSTATUS/C*1, PARALLEL_SHARED_PROC/I, PARALLEL/SHARED_HANDLE/H, PARALLEL_SHARED_PROCS/I*NP, PARALLEL_SHARED_HANDLES/H*NP</td>
-<td> Data which describes parallel mesh</td>
-</tr>
-<tr>
-<td>Structured mesh constructs</td>
-<td>S</td>
-<td>BOX_DIMS/I*6, GLOBAL_BOX_DIMS/I*6, BOX_PERIODIC/2*I, __BOX_SET/O</td>
-<td>Data describing structured mesh </td>
-</tr>
-<tr>
-<td>Spectral mesh constructs </td>
-<td>E, S</td>
-<td>SPECTRAL_ORDER/I, SPECTRAL_VERTICES/I*(O+1)^2</td>
-<td>Data marking spectral mesh constructs</td>
-</tr>
-</table>
- 
-  \ref meta-introduction "Back to Introduction"
-
-  \subsection table2 Table 2: Summary of MOAB conventional tag names, types, and purposes.  Data types are I=integer, D=double, C=character, H=entity handle,O=opaque.  Data type with *x denote length of x elements of that data type.
-
-<Table border="1">
-<tr>
-<th>Tag name</th>
-<th>Data type</th>
-<th>Applies to (E=entity, S=set)</th>
-<th>Purpose</th>
-</tr>
-<tr>
-<td>BOX_DIMS</td>
-<td>I*6</td>
-<td>S</td>
-<td>Lower and upper ijk dimensions of box, ordered (ilo, jlo, klo, ihi, jhi, khi)</td>
-</tr>
-<tr>
-<td>BOX_PERIODIC</td>
-<td>I*2</td>
-<td>S</td>
-<td>Indicates whether box is periodic in i (BOX_PERIODIC[0]) or j (BOX_PERIODIC[1])</td>
-</tr>
-<tr>
-<td>__BOX_SET</td>
-<td>O</td>
-<td>S</td>
-<td>Pointer to corresponding ScdBox instance</td>
-</tr>
-<tr>
-<td>CATEGORY</td>
-<td>C*32</td>
-<td>S</td>
-<td>String describing purpose of set; examples include “group”, “vertex”, “edge”, “surface”, “volume”</td>
-</tr>
-<tr>
-<td>DIRICHLET_SET </td>
-<td>I</td>
-<td>SO</td>
-<td>Entities or sets with common boundary condition</td>
-</tr>
-<tr>
-<td>GEOM_DIMENSION</td>
-<td>I</td>
-<td>S</td>
-<td>Identifies mesh entities resolving a given geometric model entity</td>
-</tr>
-<tr>
-<td>GEOM_SENSE_2</td>
-<td>EH*2</td>
-<td>S</td>
-<td> Stored on face-type geometric topology sets, values store regions having forward and reverse sense</td>
-</tr>
-<tr>
-<td>GEOM_SENSE_N_ENTS</td>
-<td>EH*N</td>
-<td>S</td>
-<td>Stored on edge-type geometric topology sets, values store faces whose senses are stored in GEOM_SENSE_N_SENSES.</td>
-</tr>
-<tr>
-<td>GEOM_SENSE_N_SENSES</td>
-<td>I*N</td>
-<td>S</td>
-<td>Stored on edge-type geometric topology sets, values store senses of the edge with respect to faces stored in GEOM_SENSE_N_ENTS.</td>
-</tr>
-<tr>
-<td>GLOBAL_ID</td>
-<td>I</td>
-<td>E,S</td>
-<td>Application-specific entity id</td>
-</tr>
-<tr>
-<td>MATERIAL_SET</td>
-<td>I</td>
-<td>S</td>
-<td>Entities or sets grouped by material type</td>
-</tr>
-<tr>
-<td>NAME</td>
-<td>C*32</td>
-<td>E, S</td>
-<td>User-assigned entity name(s); multiple names delimited with ?</td>
-</tr>
-<tr>
-<td>NEUMANN_SET</td>
-<td>I</td>
-<td>S</td>
-<td>Entities or sets with common boundary condition </td>
-</tr>
-<tr>
-<td>PARALLEL_PART </td>
-<td>I</td>
-<td>S</td>
-<td>Represent a part in a partition</td>
-</tr>
-<tr>
-<td>PARALLEL_PARTITION</td>
-<td>I</td>
-<td>S</td>
-<td>Represents a partition of the mesh for parallel solution, which is a collection of parts</td>
-</tr>
-<tr>
-<td>__PARALLEL_SHARED_HANDLEd</td>
-<td>H</td>
-<td>E, S</td>
-<td> Handle of this entity/set on sharing processor</td>
-</tr>
-<tr>
-<td>__PARALLEL_SHARED_PROC</td>
-<td>I</td>
-<td>E,S</td>
-<td>Rank of other processor sharing this entity/set </td>
-</tr>
-</table>
-
-\ref meta-data-info "Top"
-
-  \section appendixB Appendix B: CCMIO (Star-CD, Star-CCM+) Reader/Writer Conventions
-
-  \subsection table3 Table 3: Translation between CCMIO options and MOAB tags.
-<Table border="1">
-<tr>
-<th> Set Type</th>
-<th>CCMIO Construct</th>
-<th>MOAB Tag Name, Type</th>
-</tr>
-<tr>
-<td rowspan="2">File set / Interface</td>
-<td>Title (option)</td>
-<td>“Title” (C*32)</td>
-</tr>
-<tr>
-<td>CreatingProgram</td>
-<td>“CreatingProgram” (C*32)</td>
-</tr>
-<tr>
-<td rowspan="13">Material sets</td>
-<td>Index</td>
-<td>MATERIAL_SET</td>
-</tr>
-<tr>
-<td>Label<sup>1</sup></td>
-<td>NAME</td>
-</tr>
-<tr>
-<td>MaterialId</td>
-<td>“MaterialId” (I)</td>
-</tr>
-<tr>
-<td>Radiation</td>
-<td>“Radiation” (I)</td>
-</tr>
-<tr>
-<td>PorosityId</td>
-<td>“PorosityId” (I)</td>
-</tr>
-<tr>
-<td>SpinId</td>
-<td>“SpinId” (I)</td>
-</tr>
-<tr>
-<td>GroupId</td>
-<td>“GroupId” (I)</td>
-</tr>
-<tr>
-<td>ColorIdx</td>
-<td>“ColorIdx” (I)</td>
-</tr>
-<tr>
-<td>ProcessorId</td>
-<td>“ProcessorId” (I)</td>
-</tr>
-<tr>
-<td>LightMaterial</td>
-<td>“LightMaterial” (I)</td>
-</tr>
-<tr>
-<td>FreeSurfaceMaterial</td>
-<td>“Thickness” (F)</td>
-</tr>
-<tr>
-<td>Thickness</td>
-<td>“Thickness” (F)</td>
-</tr>
-<tr>
-<td>MaterialType</td>
-<td>“MaterialType” (C*32)</td>
-</tr>
-<tr>
-<td rowspan="5">Neumann sets</td>
-<td>Index</td>
-<td>NEUMANN_SET</td>
-</tr>
-<tr>
-<td>Label</td>
-<td>NEUMANN_SET</td>
-</tr>
-<tr>
-<td>BoundaryName</td>
-<td>NAME</td>
-</tr>
-<tr>
-<td>BoundaryType</td>
-<td>“BoundaryType” (C*32)</td>
-</tr>
-<tr>
-<td>ProstarRegionNumber</td>
-<td>“ProstarRegionNumber” (I)</td>
-</tr>
-</table>
-
-Notes:
-1. If no name is present, labels the material group with “MaterialX”, where X is the index of that group.
-
-\ref meta-data-info "Top"
-
-  \section appendixC Appendix C: ExodusII Reader/Writer Conventions 
-
-  \subsection table4 Table 4: Translation between ExodusII constructs and MOAB tags.
-<Table border="1">
-<tr>
-<th> Data Type</th>
-<th>ExodusII Construct</th>
-<th>MOAB Tag Name, Type</th>
-</tr>
-<tr>
-<td></td>
-<td>QA records</td>
-<td>“qaRecord” (C*(v))<sup>2</sup></td>
-</tr>
-<tr>
-<td rowspan="2">Material sets</td>
-<td>Block number</td>
-<td>MATERIAL_SET</td>
-</tr>
-<tr>
-<td>Block element type</td>
-<td>Entity type, # vertices per entity</td>
-</tr>
-<tr>
-<td rowspan="2">Dirichlet sets<sup>3</sup></td>
-<td>Nodeset number</td>
-<td>DIRICHLET_SET</td>
-</tr>
-<tr>
-<td>Distribution factors</td>
-<td>“distFactor” (D*(v))<sup>1</sup></td>
-</tr>
-<tr>
-<td>Neumann sets</td>
-<td>Sideset number</td>
-<td>NEUMANN_SET</td>
-</tr>
-<tr>
-<td rowspan="2">Neumann sets, reverse faces3<sup>3</sup></td>
-<td>Distribution factors</td>
-<td>“distFactor” (D*(v))<sup>1</sup></td>
-</tr>
-<tr>
-<td>Sides</td>
-<td>SENSE</td>
-</tr>
-<tr>
-<td>Nodes, elements</td>
-<td>node_num_map, elem_map</td>
-<td>GLOBAL_ID on nodes/elements</td>
-</tr>
-</table>
-
-Notes:
--# Variable-length tag used for distribution factors; length for each set is the number of entities in
-each set, such that there is one distribution factor for each entity in the set.
--# QA records are stored as variable-length tags on file set specified on read. Tag is a
-concatenation of QA record strings into a single string, with '\0' used to delimit lines.
--# MOAB represents sidesets as sets of faces, rather than as sides of elements. Faces can be
-ordered “forward” or “reverse” with respect to one of the bounding elements, depending on
-whether the right-hand normal points into or out of the element. Forward-sense faces are added
-to the Neumann set. Reverse-sense faces are put into a separate set; that set is tagged with the SENSE tag, with value = -1; and that reverse set is added to the Neummann set.
-.
-
-  \ref meta-data-info "Top"
-
-  \section appendixD Appendix D: NC (Climate Data) Reader/Writer Conventions
-
-The climate data reader in MOAB reads files with the '.nc' filename extension. By default, this reader
-reads the whole mesh in the file and creates it as structured mesh in MOAB, with the mesh accessible
-through MOAB's structured mesh interface. By default, all variables and timesteps are read from the
-file, and written as tags on the mesh vertices from that file. This behavior is controlled by the
-“variable”, “nomesh”, “timestep”, and “timeval” options described earlier in this document. If MOAB
-is compiled for parallel execution and configured with a pnetcdf reader, the mesh is read in parallel,
-with a 1D or 2D decomposition designed to balance read performance and communication interface
-size (for details on the partitioning method used, see the src/io/ReadNC.cpp source file).
-
-Mesh is put into the entity set provided to the load_file function. This entity set is also annotated with
-various tags representing information read from the file. These tags are described in Table 5.
-
-Several other things to note about reading climate data files into MOAB:
-- Time-dependent variables: MOAB currently has no mechanism for time-dependent tags. Therefore, time-dependent variables are represented using one tag per timestep, with the tag name set as the variable name plus the timestep index. Thus, the first few timesteps for the variable TEMPERATURE would be represented in tags named TEMPERATURE0, TEMPERATURE1, etc.
-- Cell- and face-centered variables: The climate data reader currently does not do cell- and face-
-centered variables correctly.
-.
-  \subsection table5 Table 5: Summary of MOAB conventional tag names, types, and purposes. Data types are I=integer, D=double, C=character, H=entity handle. Data type with *x denote length of x elements of that data type; data type with *var denote variable-length tag. Tag names with two underscores prepended (“__”) denote tags not written to a file by MOAB.
-
-<Table border="1">
-<tr>
-<th> Tag name </th>
-<th>Data type </th>
-<th> Applies to (E=entity, S=set) </th>
-<th>Purpose </th>
-</tr>
-<tr>
-<td>__NUM_DIMS </td>
-<td>I</td>
-<td>S</td>
-<td>The number of dimensions in the netcdf file.</td>
-</tr>
-<tr>
-<td>__NUM_VARS</td> 
-<td>I</td>
-<td>S</td>
-<td>The number of variables in the netcdf file.</td>
-</tr>
-<tr>
-<td>__DIM_NAMES </td>
-<td>C*var </td>
-<td>S </td>
-<td>The dimension names, concatenated into a
-character string, with '\0' terminating each name.
- </td>
-</tr>
-<tr>
-<td>__DIM_NAMES 
-</td>
-<td>C*var</td>
-<td>S</td>
-<td>The variable names, concatenated into a character
-string, with '\0' terminating each name.
-</td>
-</tr>
-<tr>
-<td><dim_name> 
-</td>
-<td>(I or 
-D)*va 
-</td>
-<td>S</td>
-<td>For each dimension, the values for the dimension.
-The data type for this tag corresponds to that in the
-netcdf file. The length of this tag is the number of
-values stored for the dimension in the netcdf file.</td>
-</tr>
-<tr>
-<td>__<dim_name>_LOC_MIN MAX</td> 
-<td>2*(I or D)</td>
-<td>S</td>
-<td>The indices (0-based) of the local min and max
-values of dimension stored locally. For spatial
-dimensions like lon or lat, this will store the
-minimum and maximum indices in the loca</td>
-</tr>
-<tr>
-<td >__<dim_name>_LOC_VAL </td> 
-<td>(I or D)*var </td>
-<td>S</td>
-<td>The indices (0-based) of the dimension stored
-locally. This tag only makes sense for dimensions
-that can be read in multiple pieces, such as time.
-Only one of __<dim_name>_LOC_VALS and
-_LOC_MIN_MAX can be used for a given
-dimension.
-</tr>
-<tr>
-<td>__<var_name>_DIMS 
-</td>
-<td>C*n 
-</td>
-<td>S</td>
-<td>For each variable, the tag handles for the
-dimensions defining this variable, in netcdf
-ordering (last dimension varying fastest). The
-length of this tag, n, is # dimensions for the
-variable * sizeof(TagHandle).
-</td>
-</tr>
-<tr>
-<td><var_name><timestep_ind> 
-</td>
-<td>(data type)</td>
-<td>E</td>
-<td>Values of the variable for timestep <timestep_ind>
-for vertices. The data type of this tag corresponds
-to that of the variable from the netcdf file.
-Timestep index is 0-based.
-</td>
-</tr>
-<tr>
-<td>__GLOBAL_ATTRIBS 
-</td>
-<td>C*Var 
-</td>
-<td>S</td>
-<td>The global attributes, concatenated into a character
-string, with ‘\0’ terminating each attribute name, ‘;’
-       separating the data type and value, and ‘;’
-          separating one name/data type/value from the next.
-</td>
-</tr>
-<tr>
-<td>__GLOBAL_ATTRIBS_LEN 
-</td>
-<td>I*Var 
-</td>
-<td>S</td>
-<td>A vector of integers, marking the end position of
-each attribute (name/data type/value) in __GLOBAL_ATTRIBS tag.
-</td>
-</tr>
-<tr>
-<td>__<var_name>_ATTRIBS 
-</td>
-<td>C*Var
-</td>
-<td>S</td>
-<td>The variable attributes, concatenated into a
-character string, with ‘\0’ terminating each attribute
-   name, ‘;’ separating the data type and value, and ‘;’
-          separating one name/data type/value from the next.
-</td>
-</tr>
-<tr>
-<td>__<var_name>_ATTRIBS_LEN 
-</td>
-<td>I*Var
-</td>
-<td>S</td>
-<td>A vector of integers, marking the end position of
-each attribute (name/data type/value) in
-__<var_name>_ATTRIBS tags
-</td>
-</tr>
-</table>
-
-  \ref meta-data-info "Top"
-
-  \section appendixE Appendix E: Nek5000 Reader/Writer Conventions
-
-Nek5000, or Nek, is a code that uses the spectral element method to model fluid, heat transfer,
-electromagnetics, and other physics. Nek uses unstructured hexahedral meshes, with each hex element
-resolved by a structured grid of “Gauss Lebato Legendre” (GLL) points. Nek can read meshes through
-MOAB, and can output physics variables and GLL points through MOAB as well.
-
-Since fluid is a single material in Nek, no material sets are needed. Boundary conditions are mapped to
-Nek's cbc array using Neumann sets and a user-provided “usr_moab2nek” subroutine (for an example
-of this subroutine, see examples/moab/pipe.usr in the Nek source code). GLL point locations and fluid
-variables on those points are stored in tags on the hex elements. All hex elements have the same
-number of GLL points. The number of GLL points in each direction is stored in a tag on the mesh
-instance. These tags are described in Table 6.
-
-GLL point locations and fluid variables are stored in lexicographic order, similar to their storage order
-inside the Nek code.
 
-  \subsection table6 Table 6: Summary of MOAB conventional tag names, types, and purposes for Nek. Data types are I=integer, D=double, C=character, H=entity handle. Data type with *x denote length of x elements of that data type; data type with *var denote variable-length tag. Tag names with two underscores prepended (“__”) denote tags not written to a file by MOAB.
-<Table border="1">
-<tr>
-<th> Tag name </th>
-<th> Data Type</th>
-<th>Applies to (E=entity, S=set)</th>
-<th>Purpose</th>
-</tr>
-<tr>
-<td>SEM_DIMS</td>
-<td>I*3</td>
-<td>S</td>
-<td>The dimensions of the GLL mesh in each hex
-element.
-</td>
-</tr>
-<tr>
-<td>SEM_X</td>
-<td>D*nx*ny*nz</td>
-<td>E</td>
-<td>X position of GLL points (having nx*ny*nz
-values)
-</td>
-</tr>
-<tr>
-<td>SEM_Y</td>
-<td>D*nx*ny*nz</td>
-<td>E</td>
-<td>Y position of GLL points (having nx*ny*nz values)</td>
-</tr>
-<tr>
-<td>SEM_Z</td>
-<td>D*nx*ny*nz</td>
-<td>E</td>
-<td>Z position of GLL points (having nx*ny*nz values)</td>
-</tr>
-<tr>
-<td>VEL_X</td>
-<td>D*nx*ny*nz</td>
-<td>E</td>
-<td>Fluid velocities in the x direction for GLL point
-array (having nx*ny*nz values)</td>
-</tr>
-<tr>
-<td>VEL_Y</td>
-<td>D*nx*ny*nz</td>
-<td>E</td>
-<td>Fluid velocities in the y direction for GLL point
-array (having nx*ny*nz values)</td>
-</tr>
-<tr>
-<td>VEL_Z</td>
-<td>D*nx*ny*nz</td>
-<td>E</td>
-<td>Fluid velocities in the z direction for GLL point
-array (having nx*ny*nz values)</td>
-</tr>
-<tr>
-<td>TEMP</td>
-<td>D*nx*ny*nz</td>
-<td>E</td>
-<td>Fluid temperature for GLL point array (having
-nx*ny*nz values)
-</td>
-</tr>
-<tr>
-<td>PRESS</td>
-<td>D*nx*ny*nz</td>
-<td>E</td>
-<td>Fluid pressure for GLL point array (having
-nx*ny*nz values)
-</td>
-</tr>
-</table>
-  \ref meta-data-info "Top"
-	*/

diff --git a/doc/DG/styleguide.h b/doc/DG/styleguide.h
new file mode 100644
index 0000000..3a13e45
--- /dev/null
+++ b/doc/DG/styleguide.h
@@ -0,0 +1,91 @@
+/*!
+  \page styleguide Coding Style Guide
+Code developed in %MOAB should follow the coding styles described here.  Any deviations from this style
+guide will result in severe berating and other verbal abuse.
+
+\section dirstructure MOAB Directory Structure
+%MOAB source code is organized in the following directory structure: \n
+ - doc: Documentation is put here, along with the input file for Doxygen.  Most %MOAB documentation is doxygen-processed.
+ - examples: Examples of %MOAB usage, both small and large.  These programs are not meant to be used as unit tests, but
+     rather as further documentation on %MOAB usage.
+ - src : Mesh related source codes. It includes:
+   - io: %MOAB Input/Output classes.
+   - moab: %MOAB core classes.
+   - lotte: Computational Meshing basics.
+   - parallel: Parallel mesh computation, i/o data processing methods.
+ - test: All unit test programs should go below this directory.
+   Please put the unit tests into their related subdirectories based on the test's
+   purpose if possible.
+If you're designing a new class or other code for %MOAB and are not sure where to put it, try to find something similar
+and put it there.  Otherwise, email the %MOAB email list for pointers.  <em> In general, you should not need to create new
+subdirectories in the %MOAB source code, except when implementing a new algorithm with more than about 2 files.</em>
+
+\section sourcestyle Source Code Style and Best Practices
+%MOAB code should abide by the following general rules:
+ - Names:
+   - Class names should be in the CamelBack style, e.g. EdgeMesh or VertexMesher.
+   - Class member variables should be camelBack, e.g. EdgeMesh::schemeType; each member variable, e.g. int memberVariable, 
+   should have set/get functions void member_variable(int newval) and int member_variable(), respectively.
+   - Enumeration values should be all captitalized, with underscores avoided if possible (the enumeration name indicates
+     the general purpose of the enumeration, so e.g. we use EQUAL, not EQUAL_MESH)
+ - Source code should not contain tabs or MS-DOS newlines; tabs and other indentations should be set to a width of 2 spaces.
+   For general tips on how to set your editor for this, see the %MOAB-dev discussion starting with <a href="https://lists.mcs.anl.gov/mailman/private/moab-dev/2011/000519.html">this message</a>.
+ - Each class header should be fully commented; that includes:
+   - A \\file comment block at the top of the file; DO NOT include things like Author and Date blocks; this stuff is available
+     from subversion if we really need to know.
+   - A \\class comment block, formatted like those in the %MOAB core classes.  THE FIELDS AFTER THE CLASS NAME ARE VERY IMPORTANT,
+     as they tell developers how to include the class declaration in their code.  This information goes into the "Detailed
+     Description" portion of the class documentation.  This block should include any features or limitations of the class.
+     Eventually, we'll impose some standard boilerplate that each meshing class should use.
+     Until then, please keep this block to around a paragraph.
+   - Each function in both the public and private interfaces should be commented, INCLUDING ANY ARGUMENTS AND RETURN VALUES.
+     See the %MOAB classes for examples of how to format these comments.  As a rule of thumb, your code should run through
+     Doxygen without generating any warnings; in fact, Doxygen is sometimes helpful at pointing out inconsistencies in your
+     class declaration.
+ - Developers should avoid using \#include in header files, as they propagate dependencies more widely than necessary.  The only
+   cases where other includes are needed are to import the declaration for a parent class, and to declare types used as
+   non-pointer and non-reference function arguments.  In most cases, a forward-declaration statement (e.g. 'class MKCore') 
+   will suffice.
+ - Naming classes and other top-level constructs:
+   - No names should be added to the global namespace.  Everything should be
+     in the MOAB namespace.  An exception can be made for names with a static
+     scope declared in a .cpp file, but class member functions never have a
+     static scope.
+   - Names should be kept as private as possible.  If declaring a struct or 
+     utility class that is used internally by some other class, consider 
+     defining it in the .cpp file of the main class or a separate header 
+     only included in that .cpp file and using (if necessary) only forward
+     delcarations (e.g. \c struct \c Point3D;) in the header file used
+     by other code.  If that is not possible, then consider nesting the
+     definitions such that the scope of the name is limited to that of the
+     class using it. 
+   - Any names introduced into the top-level MOAB namespace should be
+     sufficiently unique to avoid conflicts with other code.  If you must 
+     introduce a class to the top-level MOAB namespace, don't choose
+     an overly genereric name like \c Point3D .
+ - Constants and Macros
+   - Don't use a pre-processor macro where a const variable or an inline or
+     template function will suffice.
+     There is absolutely benefit to the former over the later with modern 
+     compilers.  Further, using  macros bypasses typechecking that the compiler
+     would otherwise do for you and if used in headers, introduce names into
+     the global rather than MOAB namespace.
+   - Don't define constants that are already provided by standard libraries.
+     For example, use \c M_PI as defined in \c math.h rather than defining
+     your own constant.
+\section commits Making Repository Commits
+As a general rule, developers should update frequently, and commit changes often.  However, the repository should always remain
+in a state where the code can be compiled.  Most of the time, the code should also successfully execute "make check" run from the
+top-level directory.  If you commit code that violates this principal, it should be your first priority to return the repository
+code to a compilable state, and your second priority to make sure "make check" runs without errors.
+
+Commits to the repository should also come with a non-trivial, useful, non-verbose log message.  Oftentimes the best way to generate
+this message is to run 'commit -a', and include a comment on 
+each file that changed, then Ctrl+O to write out, followed by 'Enter' and Ctrl+X.  Many times it is helpful to state that 'make check runs successfully' at the end of the log message.
+Although it would be possible and many software projects do it, we prefer not to force successful execution of the test suite 
+before every commit.  Developers should make every effort to avoid having to impose this constraint, by running a make check
+before every commit.
+
+Top: \ref index 
+  
+ */

diff --git a/doc/MOAB-UG.doc b/doc/MOAB-UG.doc
index 281d619..b7668b8 100644
Binary files a/doc/MOAB-UG.doc and b/doc/MOAB-UG.doc differ

This diff is so big that we needed to truncate the remainder.

https://bitbucket.org/fathomteam/moab/commits/773c1b6242aa/
Changeset:   773c1b6242aa
Branch:      None
User:        tautges
Date:        2013-09-11 23:50:53
Summary:     These changes hadn't made it into my previous commits for some reason.

Affected #:  3 files

diff --git a/src/AdaptiveKDTree.cpp b/src/AdaptiveKDTree.cpp
index 92a099d..f66acbc 100644
--- a/src/AdaptiveKDTree.cpp
+++ b/src/AdaptiveKDTree.cpp
@@ -1956,23 +1956,15 @@ namespace moab {
                   }
                   tris_out[w] = *iter;
                   dists_out[w] = tri_t;
-                  ray_end = dists_out.back();
+                  if (tris_out.size() >= (unsigned)max_ints)
+                      // when we have already reached the max intx points, we cans safely reset
+                      // ray_end, because we will accept new points only "closer" than the last one
+                    ray_end = dists_out.back();
                 }
               }
-              int w = tris_out.size() - 1;
-              for (; w > 0 && tri_t < dists_out[w-1]; --w) {
-                tris_out[w] = tris_out[w-1];
-                dists_out[w] = dists_out[w-1];
-              }
-              tris_out[w] = *iter;
-              dists_out[w] = tri_t;
-              if (tris_out.size() >= (unsigned)max_ints)
-                // when we have already reached the max intx points, we cans safely reset
-                // ray_end, because we will accept new points only "closer" than the last one
-                ray_end = dists_out.back();
             }
           }
-
+          
           continue;
         }
     

diff --git a/src/io/NCHelperMPAS.cpp b/src/io/NCHelperMPAS.cpp
index 45d1b00..c0605e8 100644
--- a/src/io/NCHelperMPAS.cpp
+++ b/src/io/NCHelperMPAS.cpp
@@ -1,6 +1,6 @@
 #include "NCHelperMPAS.hpp"
 #include "moab/ReadUtilIface.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "moab/SpectralMeshTool.hpp"
 #include "MBTagConventions.hpp"
 

diff --git a/src/io/ReadNC.cpp b/src/io/ReadNC.cpp
index 50225df..a27a89d 100644
--- a/src/io/ReadNC.cpp
+++ b/src/io/ReadNC.cpp
@@ -3,7 +3,7 @@
 
 #include "moab/ReadUtilIface.hpp"
 #include "MBTagConventions.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 
 #define ERRORR(rval, str) \
   if (MB_SUCCESS != rval) { readMeshIface->report_error("%s", str); return rval; }


https://bitbucket.org/fathomteam/moab/commits/8a984314004e/
Changeset:   8a984314004e
Branch:      None
User:        tautges
Date:        2013-09-11 23:52:46
Summary:     Removing these files.

Affected #:  3 files

diff --git a/doc/dev.dox.in b/doc/dev.dox.in
deleted file mode 100644
index ecc27fa..0000000
--- a/doc/dev.dox.in
+++ /dev/null
@@ -1,842 +0,0 @@
- # Doxyfile 1.2.11.1
-
-# This file describes the settings to be used by the documentation system
-# doxygen (www.doxygen.org) for a project
-#
-# All text after a hash (#) is considered a comment and will be ignored
-# The format is:
-#       TAG = value [value, ...]
-# For lists items can also be appended using:
-#       TAG += value [value, ...]
-# Values that contain spaces should be placed between quotes (" ")
-
-#---------------------------------------------------------------------------
-# General configuration options
-#---------------------------------------------------------------------------
-
-# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
-# by quotes) that should identify the project.
-
-PROJECT_NAME           = moab 
-
-# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
-# This could be handy for archiving the generated documentation or 
-# if some version control system is used.
-
-PROJECT_NUMBER         = 
-
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
-# base path where the generated documentation will be put. 
-# If a relative path is entered, it will be relative to the location 
-# where doxygen was started. If left blank the current directory will be used.
-
-OUTPUT_DIRECTORY       = dev
-
-# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
-# documentation generated by doxygen is written. Doxygen will use this 
-# information to generate all constant output in the proper language. 
-# The default language is English, other supported languages are: 
-# Brazilian, Chinese, Croatian, Czech, Danish, Dutch, Finnish, French, 
-# German, Hungarian, Italian, Japanese, Korean, Norwegian, Polish, 
-# Portuguese, Romanian, Russian, Slovak, Slovene, Spanish and Swedish.
-
-OUTPUT_LANGUAGE        = English
-
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
-# documentation are documented, even if no documentation was available. 
-# Private class members and static file members will be hidden unless 
-# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
-
-EXTRACT_ALL            = YES
-
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
-# will be included in the documentation.
-
-EXTRACT_PRIVATE        = YES
-
-# If the EXTRACT_STATIC tag is set to YES all static members of a file 
-# will be included in the documentation.
-
-EXTRACT_STATIC         = YES
-
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
-# undocumented members of documented classes, files or namespaces. 
-# If set to NO (the default) these members will be included in the 
-# various overviews, but no documentation section is generated. 
-# This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_MEMBERS     = NO
-
-# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
-# undocumented classes that are normally visible in the class hierarchy. 
-# If set to NO (the default) these class will be included in the various 
-# overviews. This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_CLASSES     = NO
-
-# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
-# include brief member descriptions after the members that are listed in 
-# the file and class documentation (similar to JavaDoc). 
-# Set to NO to disable this.
-
-BRIEF_MEMBER_DESC      = YES
-
-# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
-# the brief description of a member or function before the detailed description. 
-# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
-# brief descriptions will be completely suppressed.
-
-REPEAT_BRIEF           = YES
-
-# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
-# Doxygen will generate a detailed section even if there is only a brief 
-# description.
-
-ALWAYS_DETAILED_SEC    = YES
-
-# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
-# path before files name in the file list and in the header files. If set 
-# to NO the shortest path that makes the file name unique will be used.
-
-FULL_PATH_NAMES        = NO
-
-# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
-# can be used to strip a user defined part of the path. Stripping is 
-# only done if one of the specified strings matches the left-hand part of 
-# the path. It is allowed to use relative paths in the argument list.
-
-STRIP_FROM_PATH        = 
-
-# The INTERNAL_DOCS tag determines if documentation 
-# that is typed after a \internal command is included. If the tag is set 
-# to NO (the default) then the documentation will be excluded. 
-# Set it to YES to include the internal documentation.
-
-INTERNAL_DOCS          = NO
-
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
-# generate a class diagram (in Html and LaTeX) for classes with base or 
-# super classes. Setting the tag to NO turns the diagrams off.
-
-CLASS_DIAGRAMS         = YES
-
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
-# be generated. Documented entities will be cross-referenced with these sources.
-
-SOURCE_BROWSER         = YES
-
-# Setting the INLINE_SOURCES tag to YES will include the body 
-# of functions and classes directly in the documentation.
-
-INLINE_SOURCES         = YES
-
-# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
-# doxygen to hide any special comment blocks from generated source code 
-# fragments. Normal C and C++ comments will always remain visible.
-
-STRIP_CODE_COMMENTS    = NO
-
-# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
-# file names in lower case letters. If set to YES upper case letters are also 
-# allowed. This is useful if you have classes or files whose names only differ 
-# in case and if your file system supports case sensitive file names. Windows 
-# users are adviced to set this option to NO.
-
-CASE_SENSE_NAMES       = YES
-
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
-# (but less readable) file names. This can be useful is your file systems 
-# doesn't support long names like on DOS, Mac, or CD-ROM.
-
-SHORT_NAMES            = NO
-
-# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
-# will show members with their full class and namespace scopes in the 
-# documentation. If set to YES the scope will be hidden.
-
-HIDE_SCOPE_NAMES       = NO
-
-# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
-# will generate a verbatim copy of the header file for each class for 
-# which an include is specified. Set to NO to disable this.
-
-VERBATIM_HEADERS       = YES
-
-# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
-# will put list of the files that are included by a file in the documentation 
-# of that file.
-
-SHOW_INCLUDE_FILES     = YES
-
-# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
-# will interpret the first line (until the first dot) of a JavaDoc-style 
-# comment as the brief description. If set to NO, the JavaDoc 
-# comments  will behave just like the Qt-style comments (thus requiring an 
-# explict @brief command for a brief description.
-
-JAVADOC_AUTOBRIEF      = NO
-
-# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
-# member inherits the documentation from any documented member that it 
-# reimplements.
-
-INHERIT_DOCS           = YES
-
-# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
-# is inserted in the documentation for inline members.
-
-INLINE_INFO            = YES
-
-# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
-# will sort the (detailed) documentation of file and class members 
-# alphabetically by member name. If set to NO the members will appear in 
-# declaration order.
-
-SORT_MEMBER_DOCS       = YES
-
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
-# tag is set to YES, then doxygen will reuse the documentation of the first 
-# member in the group (if any) for the other members of the group. By default 
-# all members of a group must be documented explicitly.
-
-DISTRIBUTE_GROUP_DOC   = NO
-
-# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
-# Doxygen uses this value to replace tabs by spaces in code fragments.
-
-TAB_SIZE               = 8
-
-# The GENERATE_TODOLIST tag can be used to enable (YES) or 
-# disable (NO) the todo list. This list is created by putting \todo 
-# commands in the documentation.
-
-GENERATE_TODOLIST      = YES
-
-# The GENERATE_TESTLIST tag can be used to enable (YES) or 
-# disable (NO) the test list. This list is created by putting \test 
-# commands in the documentation.
-
-GENERATE_TESTLIST      = YES
-
-# The GENERATE_BUGLIST tag can be used to enable (YES) or 
-# disable (NO) the bug list. This list is created by putting \bug 
-# commands in the documentation.
-
-GENERATE_BUGLIST       = YES
-
-# This tag can be used to specify a number of aliases that acts 
-# as commands in the documentation. An alias has the form "name=value". 
-# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
-# put the command \sideeffect (or @sideeffect) in the documentation, which 
-# will result in a user defined paragraph with heading "Side Effects:". 
-# You can put \n's in the value part of an alias to insert newlines.
-
-ALIASES                = 
-
-# The ENABLED_SECTIONS tag can be used to enable conditional 
-# documentation sections, marked by \if sectionname ... \endif.
-
-ENABLED_SECTIONS       = 
-
-# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
-# the initial value of a variable or define consist of for it to appear in 
-# the documentation. If the initializer consists of more lines than specified 
-# here it will be hidden. Use a value of 0 to hide initializers completely. 
-# The appearance of the initializer of individual variables and defines in the 
-# documentation can be controlled using \showinitializer or \hideinitializer 
-# command in the documentation regardless of this setting.
-
-MAX_INITIALIZER_LINES  = 30
-
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources 
-# only. Doxygen will then generate output that is more tailored for C. 
-# For instance some of the names that are used will be different. The list 
-# of all members will be omitted, etc.
-
-OPTIMIZE_OUTPUT_FOR_C  = NO
-
-# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
-# at the bottom of the documentation of classes and structs. If set to YES the 
-# list will mention the files that were used to generate the documentation.
-
-SHOW_USED_FILES        = YES
-
-#---------------------------------------------------------------------------
-# configuration options related to warning and progress messages
-#---------------------------------------------------------------------------
-
-# The QUIET tag can be used to turn on/off the messages that are generated 
-# by doxygen. Possible values are YES and NO. If left blank NO is used.
-
-QUIET                  = NO
-
-# The WARNINGS tag can be used to turn on/off the warning messages that are 
-# generated by doxygen. Possible values are YES and NO. If left blank 
-# NO is used.
-
-WARNINGS               = YES
-
-# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
-# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
-# automatically be disabled.
-
-WARN_IF_UNDOCUMENTED   = YES
-
-# The WARN_FORMAT tag determines the format of the warning messages that 
-# doxygen can produce. The string should contain the $file, $line, and $text 
-# tags, which will be replaced by the file and line number from which the 
-# warning originated and the warning text.
-
-WARN_FORMAT            = 
-
-# The WARN_LOGFILE tag can be used to specify a file to which warning 
-# and error messages should be written. If left blank the output is written 
-# to stderr.
-
-WARN_LOGFILE           = 
-
-#---------------------------------------------------------------------------
-# configuration options related to the input files
-#---------------------------------------------------------------------------
-
-# The INPUT tag can be used to specify the files and/or directories that contain 
-# documented source files. You may enter file names like "myfile.cpp" or 
-# directories like "/usr/src/myproject". Separate the files or directories 
-# with spaces.
-
-INPUT                  = @top_srcdir@/src \
-                         @top_srcdir@/tools \
-                         @top_srcdir@/itaps \
-			 @top_srcdir@/examples
-
-# If the value of the INPUT tag contains directories, you can use the 
-# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
-# and *.h) to filter out the source-files in the directories. If left 
-# blank all files are included.
-
-FILE_PATTERNS          = *.cpp *.hpp *.h *.dox
-#FILE_PATTERNS          = *.dox
-
-# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
-# should be searched for input files as well. Possible values are YES and NO. 
-# If left blank NO is used.
-
-RECURSIVE              = YES
-
-# The EXCLUDE tag can be used to specify files and/or directories that should 
-# excluded from the INPUT source files. This way you can easily exclude a 
-# subdirectory from a directory tree whose root is specified with the INPUT tag.
-
-EXCLUDE                = 
-
-# If the value of the INPUT tag contains directories, you can use the 
-# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
-# certain files from those directories.
-
-EXCLUDE_PATTERNS       = 
-
-# The EXAMPLE_PATH tag can be used to specify one or more files or 
-# directories that contain example code fragments that are included (see 
-# the \include command).
-
-EXAMPLE_PATH           =  
-
-# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
-# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
-# and *.h) to filter out the source-files in the directories. If left 
-# blank all files are included.
-
-EXAMPLE_PATTERNS       =
-
-# The IMAGE_PATH tag can be used to specify one or more files or 
-# directories that contain image that are included in the documentation (see 
-# the \image command).
-
-IMAGE_PATH             = 
-
-# The INPUT_FILTER tag can be used to specify a program that doxygen should 
-# invoke to filter for each input file. Doxygen will invoke the filter program 
-# by executing (via popen()) the command <filter><input-file>, where <filter> 
-# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
-# input file. Doxygen will then use the output that the filter program writes 
-# to standard output.
-
-INPUT_FILTER           = 
-
-# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
-# INPUT_FILTER) will be used to filter the input files when producing source 
-# files to browse.
-
-FILTER_SOURCE_FILES    = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the alphabetical class index
-#---------------------------------------------------------------------------
-
-# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
-# of all compounds will be generated. Enable this if the project 
-# contains a lot of classes, structs, unions or interfaces.
-
-ALPHABETICAL_INDEX     = YES
-
-# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
-# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
-# in which this list will be split (can be a number in the range [1..20])
-
-COLS_IN_ALPHA_INDEX    = 5
-
-# In case all classes in a project start with a common prefix, all 
-# classes will be put under the same header in the alphabetical index. 
-# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
-# should be ignored while generating the index headers.
-
-IGNORE_PREFIX          = 
-
-#---------------------------------------------------------------------------
-# configuration options related to the HTML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
-# generate HTML output.
-
-GENERATE_HTML          = YES
-
-# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `html' will be used as the default path.
-
-HTML_OUTPUT            = 
-
-# The HTML_HEADER tag can be used to specify a personal HTML header for 
-# each generated HTML page. If it is left blank doxygen will generate a 
-# standard header.
-
-HTML_HEADER            = 
-
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
-# each generated HTML page. If it is left blank doxygen will generate a 
-# standard footer.
-
-HTML_FOOTER            = 
-
-# The HTML_STYLESHEET tag can be used to specify a user defined cascading 
-# style sheet that is used by each HTML page. It can be used to 
-# fine-tune the look of the HTML output. If the tag is left blank doxygen 
-# will generate a default style sheet
-
-HTML_STYLESHEET        = 
-
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
-# files or namespaces will be aligned in HTML using tables. If set to 
-# NO a bullet list will be used.
-
-HTML_ALIGN_MEMBERS     = YES
-
-# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
-# will be generated that can be used as input for tools like the 
-# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
-# of the generated HTML documentation.
-
-GENERATE_HTMLHELP      = NO
-
-# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
-# controls if a separate .chi index file is generated (YES) or that 
-# it should be included in the master .chm file (NO).
-
-GENERATE_CHI           = NO
-
-# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
-# controls whether a binary table of contents is generated (YES) or a 
-# normal table of contents (NO) in the .chm file.
-
-BINARY_TOC             = NO
-
-# The TOC_EXPAND flag can be set to YES to add extra items for group members 
-# to the contents of the Html help documentation and to the tree view.
-
-TOC_EXPAND             = NO
-
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
-# top of each HTML page. The value NO (the default) enables the index and 
-# the value YES disables it.
-
-DISABLE_INDEX          = NO
-
-# This tag can be used to set the number of enum values (range [1..20]) 
-# that doxygen will group on one line in the generated HTML documentation.
-
-ENUM_VALUES_PER_LINE   = 4
-
-# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
-# generated containing a tree-like index structure (just like the one that 
-# is generated for HTML Help). For this to work a browser that supports 
-# JavaScript and frames is required (for instance Netscape 4.0+ 
-# or Internet explorer 4.0+).
-
-GENERATE_TREEVIEW      = YES
-
-# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
-# used to set the initial width (in pixels) of the frame in which the tree 
-# is shown.
-
-TREEVIEW_WIDTH         = 250
-
-#---------------------------------------------------------------------------
-# configuration options related to the LaTeX output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
-# generate Latex output.
-
-GENERATE_LATEX         = NO
-
-# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `latex' will be used as the default path.
-
-LATEX_OUTPUT           = 
-
-# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
-# LaTeX documents. This may be useful for small projects and may help to 
-# save some trees in general.
-
-COMPACT_LATEX          = NO
-
-# The PAPER_TYPE tag can be used to set the paper type that is used 
-# by the printer. Possible values are: a4, a4wide, letter, legal and 
-# executive. If left blank a4wide will be used.
-
-PAPER_TYPE             = letter
-
-# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
-# packages that should be included in the LaTeX output.
-
-EXTRA_PACKAGES         = 
-
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
-# the generated latex document. The header should contain everything until 
-# the first chapter. If it is left blank doxygen will generate a 
-# standard header. Notice: only use this tag if you know what you are doing!
-
-LATEX_HEADER           = 
-
-# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
-# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
-# contain links (just like the HTML output) instead of page references 
-# This makes the output suitable for online browsing using a pdf viewer.
-
-PDF_HYPERLINKS         = NO
-
-# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
-# plain latex in the generated Makefile. Set this option to YES to get a 
-# higher quality PDF documentation.
-
-USE_PDFLATEX           = NO
-
-# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
-# command to the generated LaTeX files. This will instruct LaTeX to keep 
-# running if errors occur, instead of asking the user for help. 
-# This option is also used when generating formulas in HTML.
-
-LATEX_BATCHMODE        = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the RTF output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
-# The RTF output is optimised for Word 97 and may not look very pretty with 
-# other RTF readers or editors.
-
-GENERATE_RTF           = NO
-
-# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `rtf' will be used as the default path.
-
-RTF_OUTPUT             = 
-
-# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
-# RTF documents. This may be useful for small projects and may help to 
-# save some trees in general.
-
-COMPACT_RTF            = NO
-
-# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
-# will contain hyperlink fields. The RTF file will 
-# contain links (just like the HTML output) instead of page references. 
-# This makes the output suitable for online browsing using WORD or other 
-# programs which support those fields. 
-# Note: wordpad (write) and others do not support links.
-
-RTF_HYPERLINKS         = NO
-
-# Load stylesheet definitions from file. Syntax is similar to doxygen's 
-# config file, i.e. a series of assigments. You only have to provide 
-# replacements, missing definitions are set to their default value.
-
-RTF_STYLESHEET_FILE    = 
-
-# Set optional variables used in the generation of an rtf document. 
-# Syntax is similar to doxygen's config file.
-
-RTF_EXTENSIONS_FILE    = 
-
-#---------------------------------------------------------------------------
-# configuration options related to the man page output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
-# generate man pages
-
-GENERATE_MAN           = NO
-
-# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `man' will be used as the default path.
-
-MAN_OUTPUT             = 
-
-# The MAN_EXTENSION tag determines the extension that is added to 
-# the generated man pages (default is the subroutine's section .3)
-
-MAN_EXTENSION          = 
-
-# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
-# then it will generate one additional man file for each entity
-# documented in the real man page(s). These additional files
-# only source the real man page, but without them the man command
-# would be unable to find the correct page. The default is NO.
-
-MAN_LINKS              = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the XML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_XML tag is set to YES Doxygen will 
-# generate an XML file that captures the structure of 
-# the code including all documentation. Note that this 
-# feature is still experimental and incomplete at the 
-# moment.
-
-GENERATE_XML           = NO
-
-#---------------------------------------------------------------------------
-# Configuration options related to the preprocessor   
-#---------------------------------------------------------------------------
-
-# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
-# evaluate all C-preprocessor directives found in the sources and include 
-# files.
-
-ENABLE_PREPROCESSING   = YES
-
-# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
-# names in the source code. If set to NO (the default) only conditional 
-# compilation will be performed. Macro expansion can be done in a controlled 
-# way by setting EXPAND_ONLY_PREDEF to YES.
-
-MACRO_EXPANSION        = NO
-
-# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
-# then the macro expansion is limited to the macros specified with the 
-# PREDEFINED and EXPAND_AS_PREDEFINED tags.
-
-EXPAND_ONLY_PREDEF     = NO
-
-# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
-# in the INCLUDE_PATH (see below) will be search if a #include is found.
-
-SEARCH_INCLUDES        = YES
-
-# The INCLUDE_PATH tag can be used to specify one or more directories that 
-# contain include files that are not input files but should be processed by 
-# the preprocessor.
-
-INCLUDE_PATH           = 
-
-# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
-# patterns (like *.h and *.hpp) to filter out the header-files in the 
-# directories. If left blank, the patterns specified with FILE_PATTERNS will 
-# be used.
-
-INCLUDE_FILE_PATTERNS  = 
-
-# The PREDEFINED tag can be used to specify one or more macro names that 
-# are defined before the preprocessor is started (similar to the -D option of 
-# gcc). The argument of the tag is a list of macros of the form: name 
-# or name=definition (no spaces). If the definition and the = are 
-# omitted =1 is assumed.
-
-PREDEFINED             = 
-
-# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then 
-# this tag can be used to specify a list of macro names that should be expanded. 
-# The macro definition that is found in the sources will be used. 
-# Use the PREDEFINED tag if you want to use a different macro definition.
-
-EXPAND_AS_DEFINED      = 
-
-# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
-# doxygen's preprocessor will remove all function-like macros that are alone 
-# on a line and do not end with a semicolon. Such function macros are typically 
-# used for boiler-plate code, and will confuse the parser if not removed.
-
-SKIP_FUNCTION_MACROS   = YES
-
-#---------------------------------------------------------------------------
-# Configuration::addtions related to external references   
-#---------------------------------------------------------------------------
-
-# The TAGFILES tag can be used to specify one or more tagfiles.
-
-TAGFILES               = 
-
-# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
-# a tag file that is based on the input files it reads.
-
-GENERATE_TAGFILE       = 
-
-# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
-# in the class index. If set to NO only the inherited external classes 
-# will be listed.
-
-ALLEXTERNALS           = NO
-
-# The PERL_PATH should be the absolute path and name of the perl script 
-# interpreter (i.e. the result of `which perl').
-
-PERL_PATH              = 
-
-#---------------------------------------------------------------------------
-# Configuration options related to the dot tool   
-#---------------------------------------------------------------------------
-
-# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
-# available from the path. This tool is part of Graphviz, a graph visualization 
-# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
-# have no effect if this option is set to NO (the default)
-
-HAVE_DOT               = NO
-
-# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
-# will generate a graph for each documented class showing the direct and 
-# indirect inheritance relations. Setting this tag to YES will force the 
-# the CLASS_DIAGRAMS tag to NO.
-
-CLASS_GRAPH            = YES
-
-# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
-# will generate a graph for each documented class showing the direct and 
-# indirect implementation dependencies (inheritance, containment, and 
-# class references variables) of the class with other documented classes.
-
-COLLABORATION_GRAPH    = YES
-
-# If set to YES, the inheritance and collaboration graphs will show the 
-# relations between templates and their instances.
-
-TEMPLATE_RELATIONS     = YES
-
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
-# tags are set to YES then doxygen will generate a graph for each documented 
-# file showing the direct and indirect include dependencies of the file with 
-# other documented files.
-
-INCLUDE_GRAPH          = YES
-
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
-# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
-# documented header file showing the documented files that directly or 
-# indirectly include this file.
-
-INCLUDED_BY_GRAPH      = YES
-
-# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
-# will graphical hierarchy of all classes instead of a textual one.
-
-GRAPHICAL_HIERARCHY    = YES
-
-# The tag DOT_PATH can be used to specify the path where the dot tool can be 
-# found. If left blank, it is assumed the dot tool can be found on the path.
-
-DOT_PATH               = 
-
-# The DOTFILE_DIRS tag can be used to specify one or more directories that 
-# contain dot files that are included in the documentation (see the 
-# \dotfile command).
-
-DOTFILE_DIRS           = 
-
-# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
-# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
-# this value, doxygen will try to truncate the graph, so that it fits within 
-# the specified constraint. Beware that most browsers cannot cope with very 
-# large images.
-
-MAX_DOT_GRAPH_WIDTH    = 1024
-
-# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height 
-# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
-# this value, doxygen will try to truncate the graph, so that it fits within 
-# the specified constraint. Beware that most browsers cannot cope with very 
-# large images.
-
-MAX_DOT_GRAPH_HEIGHT   = 1024
-
-# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
-# generate a legend page explaining the meaning of the various boxes and 
-# arrows in the dot generated graphs.
-
-GENERATE_LEGEND        = YES
-
-# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
-# remove the intermedate dot files that are used to generate 
-# the various graphs.
-
-DOT_CLEANUP            = YES
-
-#---------------------------------------------------------------------------
-# Configuration::addtions related to the search engine   
-#---------------------------------------------------------------------------
-
-# The SEARCHENGINE tag specifies whether or not a search engine should be 
-# used. If set to NO the values of all tags below this one will be ignored.
-
-SEARCHENGINE           = NO
-
-# The CGI_NAME tag should be the name of the CGI script that 
-# starts the search engine (doxysearch) with the correct parameters. 
-# A script with this name will be generated by doxygen.
-
-CGI_NAME               = 
-
-# The CGI_URL tag should be the absolute URL to the directory where the 
-# cgi binaries are located. See the documentation of your http daemon for 
-# details.
-
-CGI_URL                = 
-
-# The DOC_URL tag should be the absolute URL to the directory where the 
-# documentation is located. If left blank the absolute path to the 
-# documentation, with file:// prepended to it, will be used.
-
-DOC_URL                = 
-
-# The DOC_ABSPATH tag should be the absolute path to the directory where the 
-# documentation is located. If left blank the directory on the local machine 
-# will be used.
-
-DOC_ABSPATH            = 
-
-# The BIN_ABSPATH tag must point to the directory where the doxysearch binary 
-# is installed.
-
-BIN_ABSPATH            = 
-
-# The EXT_DOC_PATHS tag can be used to specify one or more paths to 
-# documentation generated for other projects. This allows doxysearch to search 
-# the documentation for these projects as well.
-
-EXT_DOC_PATHS          = 

diff --git a/examples/HelloMoabPar.cpp b/examples/HelloMoabPar.cpp
deleted file mode 100644
index a5a71aa..0000000
--- a/examples/HelloMoabPar.cpp
+++ /dev/null
@@ -1,154 +0,0 @@
-/** @example HelloMoabPar.cpp \n
- * \brief Read mesh into MOAB in parallel \n
- * This example shows the simplest way of telling MOAB to read in parallel.
- *
- *    -#  Initialize MPI and get the rank and number of processors \n
- *    -#  Process arguments (file name and options for parallel read) \n
- *    -#  Initialize MOAB \n
- *    -#  Load a partitioned file in parallel; \n
- *    -#  retrieve shared entities on each processor \n
- *    -#  Filter owned entities among shared ones on each processor \n
- *    -#  Exchange ghost layers, and repeat the reports \n
- *
- * <b>To compile</b>: \n
- *    make HelloMoabPar MOAB_DIR=<installdir>  \n
- * <b>To run</b>: mpiexec -np 4 HelloMoabPar \n
- *  (depending on your configuration, LD_LIBRARY_PATH may need to contain <hdf5>/lib folder)
- *
- */
-
-#include "moab/ParallelComm.hpp"
-#include "MBParallelConventions.h"
-#include "moab/Core.hpp"
-#include <iostream>
-
-using namespace moab;
-
-int main(int argc, char **argv)
-{
-  MPI_Init(&argc, &argv);
-
-  int nprocs, rank;
-  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
-  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
-
-  std::string filename;
-  std::string options;
-  if (3 != argc)
-  {
-    if (rank == 0)
-    {
-      std::cout << "Usage: " << argv[0] << " <filename><options (separated by;)>\n ";
-    }
-    /* this file has a partition with 4 parts */
-    filename = "../MeshFiles/unittest/disk.h5m";
-    /*  Options for reading
-     *  - read in parallel
-     *  - use PARALLEL_PARTITION tag
-     *  - resolve shared entities after reading
-    */
-    options = "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;PARALLEL_RESOLVE_SHARED_ENTS";
-  }
-  else
-  {
-    filename = argv[1];
-    options = argv[2];
-  }
-  if (rank == 0)
-    std::cout << "reading file " << filename << "\n  with options:" << options <<
-      "\n  on " << nprocs << " processors\n";
-
-  // get MOAB instance and read the file with the specified options
-  Interface *mbImpl = new Core;
-  if (NULL == mbImpl) return 1;
-  ErrorCode rval = mbImpl->load_file(filename.c_str(), 0, options.c_str());
-  if (rval != MB_SUCCESS) return 1;
-
-  // get the ParallelComm instance
-  ParallelComm* pcomm = ParallelComm::get_pcomm(mbImpl, 0);
-  MPI_Comm comm = pcomm->comm();
-  if (0 == pcomm) return 1;
-
-  // get all shared entities with other processors
-  Range shared_ents;
-  rval = pcomm->get_shared_entities(-1, // -1 means all other processors                                    Range &shared_ents,
-      shared_ents);
-  if (rval != MB_SUCCESS) return 1;
-  /* Among shared entities, get those owned by the current processor
-   * For this, use a filter operation;
-   * Each shared entity is owned by exactly one processor;
-   * An entity could be simply-shared (with exactly one other processor) or
-   *  multi-shared.
-   */
-  Range owned_entities;
-  rval = pcomm->filter_pstatus(shared_ents, // pass entities that we want to filter
-      PSTATUS_NOT_OWNED, // status we are looking for
-      PSTATUS_NOT, // operation applied ; so it will return owned entities (!not_owned = owned)
-      -1, // this means all processors
-      &owned_entities);
-  if (rval != MB_SUCCESS) return 1;
-  unsigned int nums[4]={0}; // to store the owned entities per dimension
-  for (int i=0; i<3; i++)
-  {
-    nums[i]=(int)owned_entities.num_of_dimension(i);
-  }
-  int * rbuf;
-  if (rank==0)
-    rbuf = (int *)malloc(nprocs*4*sizeof(int));
-  MPI_Gather( nums, 4, MPI_INT, rbuf, 4, MPI_INT, 0, comm);
-  // print the stats gathered:
-  if (rank == 0)
-  {
-    for (int i=0; i<nprocs; i++)
-    {
-      std::cout << " shared, owned entities on proc " << i << " :" << rbuf[4*i] << " verts, " <<
-          rbuf[4*i+1] << " edges, " << rbuf[4*i+2] << " faces\n";
-    }
-
-  }
-
-  /*
-   * Now exchange 1 layer of ghost elements, using vertices as bridge
-   *   we could have done this as part of reading process, by passing an extra read option
-   *    ";PARALLEL_GHOSTS=2.0.1.0"
-   */
-  rval = pcomm->exchange_ghost_cells(2, // int ghost_dim,
-                                     0, // int bridge_dim,
-                                     1, //int num_layers,
-                                     0, //int addl_ents,
-                                     true); // bool store_remote_handles);
-  if (rval != MB_SUCCESS) return 1;
-
-  // repeat the reports, after ghost exchange
-  shared_ents.clear();
-  owned_entities.clear();
-  rval = pcomm->get_shared_entities(-1, // -1 means all other processors                                    Range &shared_ents,
-        shared_ents);
-  if (rval != MB_SUCCESS) return 1;
-  rval = pcomm->filter_pstatus(shared_ents,
-        PSTATUS_NOT_OWNED,
-        PSTATUS_NOT,
-        -1,
-        &owned_entities);
-  if (rval != MB_SUCCESS)  return 1;
-
-  // find out how many shared entities of each dimension are owned on this processor
-  for (int i=0; i<3; i++)
-    nums[i]=(int)owned_entities.num_of_dimension(i);
-
-  // gather the statistics on processor 0
-  MPI_Gather( nums, 4, MPI_INT, rbuf, 4, MPI_INT, 0, comm);
-  if (rank == 0)
-  {
-    std::cout << " \n\n After exchanging one ghost layer: \n";
-    for (int i=0; i<nprocs; i++)
-    {
-      std::cout << " shared, owned entities on proc " << i << " :" << rbuf[4*i] << " verts, " <<
-          rbuf[4*i+1] << " edges, " << rbuf[4*i+2] << " faces\n";
-    }
-    free(rbuf);
-  }
-  MPI_Finalize();
-
-  return 0;
-}

diff --git a/examples/old/SetsNTags.cpp b/examples/old/SetsNTags.cpp
deleted file mode 100644
index 9930891..0000000
--- a/examples/old/SetsNTags.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-#include "moab/Core.hpp"
-#include "moab/Interface.hpp"
-#include "moab/Range.hpp"
-
-#ifdef USE_MPI
-#include "moab_mpi.h"
-#endif
-
-#include <iostream>
-
-int main(int argc, char **argv) {
-    // get the material set tag handle
-  moab::Tag mtag;
-  moab::ErrorCode rval;
-  const char *tag_nms[] = {"MATERIAL_SET", "DIRICHLET_SET", "NEUMANN_SET"};
-  moab::Range sets, set_ents;
-
-    // instantiate & load a file
-  moab::Interface *mb = new moab::Core();
-  const char *par_opt = "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;PARTITION_DISTRIBUTE;PARALLEL_RESOLVE_SHARED_ENTS;SETS=SETS";
-
-  bool parallel = false;
-  if (argc > 2 && !strcmp(argv[1], "-p")) parallel = true;
-  else if (argc == 1) {
-    std::cout << "Usage: " << argv[0] << "[-p] <filename>" << std::endl;
-    return 0;
-  }
-
-  if (parallel) 
-    rval = mb->load_file(argv[argc-1], 0, par_opt);
-  else
-    rval = mb->load_file(argv[argc-1]);
-  if (moab::MB_SUCCESS != rval) return 1;
-
-    // loop over set types
-  for (int i = 0; i < 3; i++) {
-    rval = mb->tag_get_handle(tag_nms[i], 1, moab::MB_TYPE_INTEGER, mtag);
-    if (moab::MB_SUCCESS != rval) return 1;
-
-      // get all the sets of that type in the mesh
-    sets.clear();
-    rval = mb->get_entities_by_type_and_tag(0, moab::MBENTITYSET, &mtag,
-                                            NULL, 1, sets);
-    if (moab::MB_SUCCESS != rval) return 1;
-
-      // iterate over each set, getting entities
-    moab::Range::iterator set_it;
-    for (set_it = sets.begin(); set_it != sets.end(); set_it++)  {
-      moab::EntityHandle this_set = *set_it;
-
-        // get the id for this set
-      int set_id;
-      rval = mb->tag_get_data(mtag, &this_set, 1, &set_id);
-      if (moab::MB_SUCCESS != rval) return 1;
-
-        // get the entities in the set, recursively
-      rval = mb->get_entities_by_handle(this_set, set_ents, true);
-      if (moab::MB_SUCCESS != rval) return 1;
-
-      std::cout << tag_nms[i] << " " << set_id << " has " 
-                << set_ents.size() << " entities:" << std::endl;
-      set_ents.print("   ");
-      set_ents.clear();
-    }
-  }
-
-    // do the same for all sets
-  sets.clear();
-  rval = mb->get_entities_by_type(0, moab::MBENTITYSET, sets);
-  if (moab::MB_SUCCESS != rval) return 1;
-
-    // print the sets
-  rval = mb->list_entities(sets);
-  if (moab::MB_SUCCESS != rval) return 1;
-
-  rval = mb->list_entities(NULL, 1);
-  
-#ifdef USE_MPI
-  if (parallel) {
-    MPI_Barrier(MPI_COMM_WORLD);
-    std::cout << std::flush;
-    std::cerr << std::flush;
-  }
-#endif
-
-  delete mb;
-}


https://bitbucket.org/fathomteam/moab/commits/beb66e92abc6/
Changeset:   beb66e92abc6
Branch:      None
User:        tautges
Date:        2013-09-12 18:42:05
Summary:     Merge branch 'master' of https://bitbucket.org/fathomteam/moab

Conflicts resolved.

Affected #:  3 files

diff --git a/itaps/imesh/iMesh_MOAB.cpp b/itaps/imesh/iMesh_MOAB.cpp
index b333969..68c0b72 100644
--- a/itaps/imesh/iMesh_MOAB.cpp
+++ b/itaps/imesh/iMesh_MOAB.cpp
@@ -3303,7 +3303,7 @@ void iMesh_createStructuredMesh(iMesh_Instance instance,
   ScdBox *scd_box;
   rval = scdi->construct_box(HomCoord(local_dims[0], local_dims[1], (-1 != local_dims[2] ? local_dims[2] : 0), 1),
                              HomCoord(local_dims[3], local_dims[4], (-1 != local_dims[5] ? local_dims[5] : 0), 1),
-                             NULL, 0, scd_box);
+                             NULL, 0, scd_box, NULL, NULL, (vert_gids ? true : false));
   CHKERR(rval, "Trouble creating scd vertex sequence.");
 
     // set the global box parameters

diff --git a/src/Core.cpp b/src/Core.cpp
index 0a077a9..ad6bdda 100644
--- a/src/Core.cpp
+++ b/src/Core.cpp
@@ -2897,7 +2897,7 @@ ErrorCode Core::list_entity(const EntityHandle entity) const
     std::cout << "   (MULTIPLE = " << multiple << ")" << std::endl;
 
   result = print_entity_tags(std::string(), entity, MB_TAG_DENSE);
-  
+
   std::cout << std::endl;
 
   return result;

diff --git a/tools/mcnpmit/main.cpp b/tools/mcnpmit/main.cpp
index c138970..7eb0011 100644
--- a/tools/mcnpmit/main.cpp
+++ b/tools/mcnpmit/main.cpp
@@ -12,7 +12,7 @@
 #include "MBTagConventions.hpp"
 #include "moab/AdaptiveKDTree.hpp"
 #include "moab/GeomUtil.hpp"
-#include "tools/mbcoupler/ElemUtil.hpp"
+#include "../tools/mbcoupler/ElemUtil.hpp"
 
 #define MBI mb_instance()
 


https://bitbucket.org/fathomteam/moab/commits/6c01eb664893/
Changeset:   6c01eb664893
Branch:      None
User:        tautges
Date:        2013-09-12 18:48:41
Summary:     Merge branch 'master' of https://bitbucket.org/fathomteam/moab

Resolved several conflicts.

Passes debug/opt tests.

Affected #:  20 files

diff --git a/src/Makefile.am b/src/Makefile.am
index 1d3556d..5f59ff3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -78,16 +78,10 @@ libMOAB_la_SOURCES = \
   OrientedBox.cpp \
   OrientedBox.hpp \
   OrientedBoxTreeTool.cpp \
-  moab/point_locater/lotte/minmax.h \
-  moab/point_locater/lotte/extrafindpt.h \
   lotte/poly.c \
-  moab/point_locater/lotte/poly.h \
   lotte/findpt.c \
-  moab/point_locater/lotte/findpt.h \
   lotte/errmem.c \
-  moab/point_locater/lotte/errmem.h \
   lotte/tensor.c \
-  moab/point_locater/lotte/tensor.h \
   PolyElementSeq.cpp \
   PolyElementSeq.hpp \
   ProgOptions.cpp \
@@ -181,10 +175,6 @@ nobase_libMOAB_la_include_HEADERS = \
   moab/point_locater/element_maps/linear_tet_map.hpp  \
   moab/point_locater/element_maps/spectral_hex_map.hpp  \
   moab/point_locater/element_maps/quadratic_hex_map.hpp  \
-  moab/point_locater/lotte/types.h  \
-  moab/point_locater/lotte/errmem.h  \
-  moab/point_locater/lotte/findpt.h  \
-  moab/point_locater/lotte/poly.h  \
   moab/point_locater/point_locater.hpp \
   moab/point_locater/parametrizer.hpp \
   moab/Matrix3.hpp \

diff --git a/src/lotte/errmem.c b/src/lotte/errmem.c
index 0196d83..b890bce 100644
--- a/src/lotte/errmem.c
+++ b/src/lotte/errmem.c
@@ -1,6 +1,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
+#include "moab/FindPtFuncs.h"
 
 void fail(const char *fmt, ...)
 {

diff --git a/src/lotte/findpt.c b/src/lotte/findpt.c
index 00fe8b7..160c7ab 100644
--- a/src/lotte/findpt.c
+++ b/src/lotte/findpt.c
@@ -5,12 +5,10 @@
 #include <float.h>
 #include <string.h>  /* for memcpy */
 
-#include "errmem.h"
-#include "types.h"
-#include "minmax.h"
-#include "poly.h"
-#include "tensor.h"
-#include "extrafindpt.h"
+#include "moab/FindPtFuncs.h"
+
+const unsigned opt_no_constraints_2 = 3+1;
+const unsigned opt_no_constraints_3 = 9+3+1;
 
 /*--------------------------------------------------------------------------
    Lobatto Polynomial Bounds
@@ -484,14 +482,6 @@ static void obbox_free_3(obbox_data_3 *p)
   free(p);
 }
 
-typedef struct {
-  real x[2], A[4], axis_bnd[4];
-} obbox_2;
-
-typedef struct {
-  real x[3], A[9], axis_bnd[6];
-} obbox_3;
-
 int obbox_axis_test_2(const obbox_2 *p, const real x[2])
 {
   return (x[0]<p->axis_bnd[0] || x[0]>p->axis_bnd[1] ||
@@ -767,34 +757,6 @@ void obbox_calc_3(const obbox_data_3 *p, real tol,
      
   --------------------------------------------------------------------------*/
 
-typedef struct {
-  unsigned hash_n;
-  real bnd[4]; /* bounds for all elements */
-  real fac[2]; /* fac[i] = hash_n / (bnd[2*i+1]-bnd[2*i]) */
-  obbox_2 *obb; /* obb[nel] -- bounding box info for each element */
-  uint *offset; /* hash table -- for cell i,j:
-                         uint index = j*hash_n+i,
-                                  b = offset[index  ],
-                                  e = offset[index+1];
-                         elements in cell are
-                           offset[b], offset[b+1], ..., offset[e-1] */
-  unsigned max; /* maximum # of elements in any cell */
-} hash_data_2;
-
-typedef struct {
-  unsigned hash_n;
-  real bnd[6]; /* bounds for all elements */
-  real fac[3]; /* fac[i] = hash_n / (bnd[2*i+1]-bnd[2*i]) */
-  obbox_3 *obb; /* obb[nel] -- bounding box info for each element */
-  uint *offset; /* hash table -- for cell i,j,k:
-                         uint index = (k*hash_n+j)*hash_n+i,
-                                  b = offset[index  ],
-                                  e = offset[index+1];
-                         elements in cell are
-                           offset[b], offset[b+1], ..., offset[e-1] */
-  unsigned max; /* maximum # of elements in any cell */
-} hash_data_3;
-
 static int ifloor(real x)
 {
   /*
@@ -1885,12 +1847,6 @@ double opt_findpt_2(opt_data_2 *p, const real *const elx[2],
      
   --------------------------------------------------------------------------*/
 
-typedef struct {
-  uint el;
-  real r[3];
-  real dist;
-} findpt_listel;
-
 /* heap sort on A[0:n-1] with key A[i]->dist
    precondition: n!=0 */
 static void findpt_list_sort(findpt_listel **A, unsigned n)
@@ -1925,34 +1881,6 @@ static void findpt_list_sort(findpt_listel **A, unsigned n)
   }
 }
 
-typedef struct {
-  const real *xw[2];   /* geometry data */
-  real *z[2];          /* lobatto nodes */
-  lagrange_data ld[2]; /* interpolation, derivative weights & data */
-  unsigned nptel;      /* nodes per element */
-  hash_data_2 *hash;   /* geometric hashing data */
-  findpt_listel *list, **sorted, **end; /* pre-allocated list of elements to
-                                           check (found by hashing), and
-                                           pre-allocated list of pointers into
-                                           the first list for sorting */
-  opt_data_2 *od; /* data for the optimization algorithm */
-  real *od_work;
-} findpt_data_2;
-
-typedef struct {
-  const real *xw[3];   /* geometry data */
-  real *z[3];          /* lobatto nodes */
-  lagrange_data ld[3]; /* interpolation, derivative weights & data */
-  unsigned nptel;      /* nodes per element */
-  hash_data_3 *hash;   /* geometric hashing data */
-  findpt_listel *list, **sorted, **end; /* pre-allocated list of elements to
-                                           check (found by hashing), and
-                                           pre-allocated list of pointers into
-                                           the first list for sorting */
-  opt_data_3 *od; /* data for the optimization algorithm */
-  real *od_work;
-} findpt_data_3;
-
 findpt_data_2 *findpt_setup_2(
           const real *const xw[2], const unsigned n[2], uint nel,
           uint max_hash_size, real bbox_tol)

diff --git a/src/lotte/poly.c b/src/lotte/poly.c
index 6b5cba6..b8a93b7 100644
--- a/src/lotte/poly.c
+++ b/src/lotte/poly.c
@@ -5,8 +5,7 @@
 #include <string.h>  /* for memcpy */
 #include <float.h>
 
-#include "errmem.h"
-#include "types.h"
+#include "moab/FindPtFuncs.h"
 
 /* 
   For brevity's sake, some names have been shortened
@@ -354,15 +353,6 @@ void lagrange_weights_deriv(const real *z, unsigned n,
      lagrange_free(&p);  // deallocate memory allocated by setup
   --------------------------------------------------------------------------*/
 
-typedef struct {
-  unsigned n;                /* number of Lagrange nodes            */
-  const real *z;             /* Lagrange nodes (user-supplied)      */
-  real *J, *D, *D2;          /* weights for 0th,1st,2nd derivatives */
-  real *J_z0, *D_z0, *D2_z0; /* ditto at z[0]   (computed at setup) */
-  real *J_zn, *D_zn, *D2_zn; /* ditto at z[n-1] (computed at setup) */
-  real *w, *d, *u0, *v0, *u1, *v1, *u2, *v2; /* work data            */
-} lagrange_data;
-
 void lagrange_0(lagrange_data *p, real x)
 {
   unsigned i, n=p->n;

diff --git a/src/lotte/tensor.c b/src/lotte/tensor.c
index 19e54b7..510dc38 100644
--- a/src/lotte/tensor.c
+++ b/src/lotte/tensor.c
@@ -1,4 +1,4 @@
-#include "types.h"
+#include "moab/FindPtFuncs.h"
 
 /*--------------------------------------------------------------------------
    Matrix-Matrix Multiplication

diff --git a/src/moab/FindPtFuncs.h b/src/moab/FindPtFuncs.h
index 3419ad2..60a464d 100644
--- a/src/moab/FindPtFuncs.h
+++ b/src/moab/FindPtFuncs.h
@@ -2,10 +2,12 @@
 #define FINDPTFUNCS_H
 
 #include "float.h"
+#include "math.h"
 
-//======================================================
-// from types.h
-//======================================================
+/*======================================================
+/ from types.h
+/======================================================
+*/
 
 /* integer type to use for everything */
 #if   defined(USE_LONG)
@@ -78,9 +80,10 @@ typedef unsigned INTEGER uint;
   typedef uint ulong;
 #endif
 
-//======================================================
-// from poly.h
-//======================================================
+/*======================================================
+/ from poly.h
+/======================================================
+*/
 
 /* 
   For brevity's sake, some names have been shortened
@@ -227,9 +230,10 @@ void lagrange_1(lagrange_data *p, real x) ;
 void lagrange_2(lagrange_data *p, real x) ;
 void lagrange_2u(lagrange_data *p) ;
 
-//======================================================
-// from tensor.h
-//======================================================
+/*======================================================
+/ from tensor.h
+/======================================================
+*/
 
 /*--------------------------------------------------------------------------
    1-,2-,3-d Tensor Application
@@ -322,37 +326,129 @@ real tensor_ig3(const real *Jr, const real *Dr, unsigned nr,
                 const real *Jt, const real *Dt, unsigned nt,
                 const real *u, real *g, real *work);
 
-//======================================================
-// from findpt.h
-//======================================================
+/*======================================================
+/ from findpt.h
+/======================================================
+*/
+
+typedef struct {
+  real x[2], A[4], axis_bnd[4];
+} obbox_2;
+
+typedef struct {
+  real x[3], A[9], axis_bnd[6];
+} obbox_3;
+
+typedef struct {
+  unsigned hash_n;
+  real bnd[4]; /* bounds for all elements */
+  real fac[2]; /* fac[i] = hash_n / (bnd[2*i+1]-bnd[2*i]) */
+  obbox_2 *obb; /* obb[nel] -- bounding box info for each element */
+  uint *offset; /* hash table -- for cell i,j:
+                         uint index = j*hash_n+i,
+                                  b = offset[index  ],
+                                  e = offset[index+1];
+                         elements in cell are
+                           offset[b], offset[b+1], ..., offset[e-1] */
+  unsigned max; /* maximum # of elements in any cell */
+} hash_data_2;
+
+typedef struct {
+  unsigned hash_n;
+  real bnd[6]; /* bounds for all elements */
+  real fac[3]; /* fac[i] = hash_n / (bnd[2*i+1]-bnd[2*i]) */
+  obbox_3 *obb; /* obb[nel] -- bounding box info for each element */
+  uint *offset; /* hash table -- for cell i,j,k:
+                         uint index = (k*hash_n+j)*hash_n+i,
+                                  b = offset[index  ],
+                                  e = offset[index+1];
+                         elements in cell are
+                           offset[b], offset[b+1], ..., offset[e-1] */
+  unsigned max; /* maximum # of elements in any cell */
+} hash_data_3;
+
+typedef struct {
+  uint el;
+  real r[3];
+  real dist;
+} findpt_listel;
+
+typedef struct {
+  unsigned constraints;
+  unsigned de, d1;
+  real *x[2], *fd1[2];
+} opt_edge_data_2;
+
+typedef struct {
+  unsigned constraints;
+  real x[2], jac[4];
+} opt_point_data_2;
+
+typedef struct {
+  lagrange_data *ld;
+  unsigned size[3];
+  const real *elx[2];
+  opt_edge_data_2 ed;
+  opt_point_data_2 pd;
+  real *work;
+  real x[2], jac[4];
+} opt_data_2;
 
 typedef struct {
   const real *xw[2];   /* geometry data */
   real *z[2];          /* lobatto nodes */
   lagrange_data ld[2]; /* interpolation, derivative weights & data */
   unsigned nptel;      /* nodes per element */
-  struct findpt_hash_data_2 *hash;   /* geometric hashing data */
-  struct findpt_listel *list, **sorted, **end;
+  hash_data_2 *hash;   /* geometric hashing data */
+  findpt_listel *list, **sorted, **end;
                                         /* pre-allocated list of elements to
                                            check (found by hashing), and
                                            pre-allocated list of pointers into
                                            the first list for sorting */
-  struct findpt_opt_data_2 *od; /* data for the optimization algorithm */
+  opt_data_2 *od; /* data for the optimization algorithm */
   real *od_work;
 } findpt_data_2;
 
 typedef struct {
+  unsigned constraints;
+  unsigned dn, d1, d2;
+  real *x[3], *fdn[3];
+} opt_face_data_3;
+
+typedef struct {
+  unsigned constraints;
+  unsigned de, d1, d2;
+  real *x[3], *fd1[3], *fd2[3];
+} opt_edge_data_3;
+
+typedef struct {
+  unsigned constraints;
+  real x[3], jac[9];
+} opt_point_data_3;
+
+typedef struct {
+  lagrange_data *ld;
+  unsigned size[4];
+  const real *elx[3];
+  opt_face_data_3 fd;
+  opt_edge_data_3 ed;
+  opt_point_data_3 pd;
+  real *work;
+  real x[3], jac[9];
+} opt_data_3;
+
+typedef struct {
   const real *xw[3];   /* geometry data */
   real *z[3];          /* lobatto nodes */
   lagrange_data ld[3]; /* interpolation, derivative weights & data */
   unsigned nptel;      /* nodes per element */
-  struct findpt_hash_data_3 *hash;   /* geometric hashing data */
-  struct findpt_listel *list, **sorted, **end;
+  hash_data_3 *hash;   /* geometric hashing data */
+  findpt_listel *list, **sorted, **end;
                                         /* pre-allocated list of elements to
                                            check (found by hashing), and
                                            pre-allocated list of pointers into
                                            the first list for sorting */
-  struct findpt_opt_data_3 *od; /* data for the optimization algorithm */
+  opt_data_3 *od; /* data for the optimization algorithm */
   real *od_work;
 } findpt_data_3;
 
@@ -375,66 +471,18 @@ int findpt_2(findpt_data_2 *p, const real x[2], int guess,
 int findpt_3(findpt_data_3 *p, const real x[3], int guess,
              uint *el, real r[3], real *dist);
 
-inline void findpt_weights_2(findpt_data_2 *p, const real r[2])
-{
-  lagrange_0(&p->ld[0],r[0]);
-  lagrange_0(&p->ld[1],r[1]);
-}
-
-inline void findpt_weights_3(findpt_data_3 *p, const real r[3])
-{
-  lagrange_0(&p->ld[0],r[0]);
-  lagrange_0(&p->ld[1],r[1]);
-  lagrange_0(&p->ld[2],r[2]);
-}
+void findpt_weights_2(findpt_data_2 *p, const real r[2]);
 
-inline double findpt_eval_2(findpt_data_2 *p, const real *u)
-{
-  return tensor_i2(p->ld[0].J,p->ld[0].n,
-                   p->ld[1].J,p->ld[1].n,
-                   u, p->od_work);
-}
+void findpt_weights_3(findpt_data_3 *p, const real r[3]);
 
-inline double findpt_eval_3(findpt_data_3 *p, const real *u)
-{
-  return tensor_i3(p->ld[0].J,p->ld[0].n,
-                   p->ld[1].J,p->ld[1].n,
-                   p->ld[2].J,p->ld[2].n,
-                   u, p->od_work);
-}
+double findpt_eval_2(findpt_data_2 *p, const real *u);
 
-//======================================================
-// from extrafindpt.h
-//======================================================
-
-typedef struct {
-  unsigned constraints;
-  unsigned dn, d1, d2;
-  real *x[3], *fdn[3];
-} opt_face_data_3;
-
-typedef struct {
-  unsigned constraints;
-  unsigned de, d1, d2;
-  real *x[3], *fd1[3], *fd2[3];
-} opt_edge_data_3;
-
-typedef struct {
-  unsigned constraints;
-  real x[3], jac[9];
-} opt_point_data_3;
-
-typedef struct {
-  lagrange_data *ld;
-  unsigned size[4];
-  const real *elx[3];
-  opt_face_data_3 fd;
-  opt_edge_data_3 ed;
-  opt_point_data_3 pd;
-  real *work;
-  real x[3], jac[9];
-} opt_data_3;
+double findpt_eval_3(findpt_data_3 *p, const real *u);
 
+/*======================================================
+/ from extrafindpt.h
+/======================================================
+*/
 
 void opt_alloc_3(opt_data_3 *p, lagrange_data *ld);
 void opt_free_3(opt_data_3 *p);
@@ -442,9 +490,6 @@ double opt_findpt_3(opt_data_3 *p, const real *const elx[3],
                            const real xstar[3], real r[3], unsigned *constr);
 void opt_vol_set_intp_3(opt_data_3 *p, const real r[3]);
 
-const unsigned opt_no_constraints_2 = 3+1;
-const unsigned opt_no_constraints_3 = 9+3+1;
-
 /* for 2d spectralQuad */
 /*--------------------------------------------------------------------------
 
@@ -452,34 +497,18 @@ const unsigned opt_no_constraints_3 = 9+3+1;
 
   --------------------------------------------------------------------------*/
 
-typedef struct {
-  unsigned constraints;
-  unsigned de, d1;
-  real *x[2], *fd1[2];
-} opt_edge_data_2;
-
-typedef struct {
-  unsigned constraints;
-  real x[2], jac[4];
-} opt_point_data_2;
-
-typedef struct {
-  lagrange_data *ld;
-  unsigned size[3];
-  const real *elx[2];
-  opt_edge_data_2 ed;
-  opt_point_data_2 pd;
-  real *work;
-  real x[2], jac[4];
-} opt_data_2;
 void opt_alloc_2(opt_data_2 *p, lagrange_data *ld);
 void opt_free_2(opt_data_2 *p);
 double opt_findpt_2(opt_data_2 *p, const real *const elx[2],
                            const real xstar[2], real r[2], unsigned *constr);
 
-//======================================================
-// from errmem.h
-//======================================================
+extern const unsigned opt_no_constraints_2;
+extern const unsigned opt_no_constraints_3;
+
+/*======================================================
+/ from errmem.h
+/======================================================
+*/
 
 /* requires:
      <stdlib.h> for malloc, calloc, realloc, free
@@ -561,6 +590,84 @@ static void buffer_free(buffer *b) { free(b->ptr); }
 #define buffer_init(b,size) buffer_init_(b,size,__FILE__)
 #define buffer_reserve(b,min) buffer_reserve_(b,min,__FILE__)
 */
+
+
+/*======================================================
+/ from minmax.h
+/======================================================
+*/
+
+/*--------------------------------------------------------------------------
+   Min, Max, Norm
+  --------------------------------------------------------------------------*/
+
+#ifdef __GNUC__
+#define MAYBE_UNUSED __attribute__ ((unused))
+#else
+#define MAYBE_UNUSED
+#endif
+
+#define DECLMINMAX(type, prefix) \
+  static type prefix##min_2(type a, type b) MAYBE_UNUSED;               \
+  static type prefix##min_2(type a, type b) {                           \
+    return b<a?b:a;                                                     \
+  }                                                                     \
+  static type prefix##max_2(type a, type b) MAYBE_UNUSED;               \
+  static type prefix##max_2(type a, type b) {                           \
+    return a>b?a:b;                                                     \
+  }                                                                     \
+  static void prefix##minmax_2(type *min, type *max, type a,            \
+                               type b) MAYBE_UNUSED;                    \
+  static void prefix##minmax_2(type *min, type *max, type a, type b) {  \
+    if(b<a) *min=b, *max=a;                                             \
+    else *min=a, *max=b;                                                \
+  }                                                                     \
+  static type prefix##min_3(type a, type b, type c) MAYBE_UNUSED;       \
+  static type prefix##min_3(type a, type b, type c) {                   \
+    return b<a?(c<b?c:b):(c<a?c:a);                                     \
+  }                                                                     \
+  static type prefix##max_3(type a, type b, type c) MAYBE_UNUSED;       \
+  static type prefix##max_3(type a, type b, type c) {                   \
+    return a>b?(a>c?a:c):(b>c?b:c);                                     \
+  }                                                                     \
+  static void prefix##minmax_3(type *min, type *max, type a, type b,    \
+                               type c) MAYBE_UNUSED;                    \
+  static void prefix##minmax_3(type *min, type *max, type a, type b,    \
+                               type c) {                                \
+    if(b<a) *min=prefix##min_2(b,c), *max=prefix##max_2(a,c);           \
+    else    *min=prefix##min_2(a,c), *max=prefix##max_2(b,c);           \
+  }
+
+DECLMINMAX(int, i)
+DECLMINMAX(unsigned, u)
+DECLMINMAX(real, r)
+#undef DECLMINMAX
+
+static real r1norm_1(real a) MAYBE_UNUSED;
+static real r1norm_1(real a) {
+  return fabsr(a);
+}
+static real r1norm_2(real a, real b) MAYBE_UNUSED;
+static real r1norm_2(real a, real b) {
+  return fabsr(a)+fabsr(b);
+}
+static real r1norm_3(real a, real b, real c) MAYBE_UNUSED;
+static real r1norm_3(real a, real b, real c) {
+  return fabsr(a)+fabsr(b)+fabsr(c);
+}
+static real r2norm_1(real a) MAYBE_UNUSED;
+static real r2norm_1(real a) {
+  return sqrtr(a*a);
+}
+static real r2norm_2(real a, real b) MAYBE_UNUSED;
+static real r2norm_2(real a, real b) {
+  return sqrtr(a*a+b*b);
+}
+static real r2norm_3(real a, real b, real c) MAYBE_UNUSED;
+static real r2norm_3(real a, real b, real c) {
+  return sqrtr(a*a+b*b+c*c);
+}
+
 #endif
 
 

diff --git a/src/moab/point_locater/element_maps/spectral_hex_map.hpp b/src/moab/point_locater/element_maps/spectral_hex_map.hpp
index 11bd573..895bc36 100644
--- a/src/moab/point_locater/element_maps/spectral_hex_map.hpp
+++ b/src/moab/point_locater/element_maps/spectral_hex_map.hpp
@@ -3,14 +3,7 @@
 
 #include "moab/Matrix3.hpp"
 #include "moab/CartVect.hpp"
-extern "C"{
-   #include "moab/point_locater/lotte/types.h"
-   #include "moab/point_locater/lotte/poly.h"
-   #include "moab/point_locater/lotte/tensor.h"
-   #include "moab/point_locater/lotte/findpt.h"
-   #include "moab/point_locater/lotte/extrafindpt.h"
-   #include "moab/point_locater/lotte/errmem.h"
-}
+#include "moab/FindPtFuncs.h"
 #include <sstream>
 #include <iomanip>
 #include <iostream>

diff --git a/src/moab/point_locater/lotte/errmem.h b/src/moab/point_locater/lotte/errmem.h
deleted file mode 100644
index d881f4a..0000000
--- a/src/moab/point_locater/lotte/errmem.h
+++ /dev/null
@@ -1,85 +0,0 @@
-#ifndef ERRMEM_H
-#define ERRMEM_H
-
-/* requires:
-     <stdlib.h> for malloc, calloc, realloc, free
-*/
-
-/*--------------------------------------------------------------------------
-   Error Reporting
-   Memory Allocation Wrappers to Catch Out-of-memory
-  --------------------------------------------------------------------------*/
-
-/* #include "malloc.h" */
-#include <stdlib.h>
-
-#ifdef __GNUC__
-void fail(const char *fmt, ...) __attribute__ ((noreturn));
-#define MAYBE_UNUSED __attribute__ ((unused))
-#else
-void fail(const char *fmt, ...);
-#define MAYBE_UNUSED
-#endif
-
-#if 0
-{}
-#endif
-
-static void *smalloc(size_t size, const char *file) MAYBE_UNUSED;
-static void *smalloc(size_t size, const char *file)
-{
-  void *res = malloc(size);
-  if(!res && size) fail("%s: allocation of %d bytes failed\n",file,(int)size);
-  return res;
-}
-
-static void *scalloc(size_t nmemb, size_t size, const char *file) MAYBE_UNUSED;
-static void *scalloc(size_t nmemb, size_t size, const char *file)
-{
-  void *res = calloc(nmemb, size);
-  if(!res && nmemb)
-    fail("%s: allocation of %d bytes failed\n",file,(int)size*nmemb);
-  return res;
-}
-
-static void *srealloc(void *ptr, size_t size, const char *file) MAYBE_UNUSED;
-static void *srealloc(void *ptr, size_t size, const char *file)
-{
-  void *res = realloc(ptr, size);
-  if(!res && size) fail("%s: allocation of %d bytes failed\n",file,(int)size);
-  return res;
-}
-
-#define tmalloc(type, count) \
-  ((type*) smalloc((count)*sizeof(type),__FILE__) )
-#define tcalloc(type, count) \
-  ((type*) scalloc((count),sizeof(type),__FILE__) )
-#define trealloc(type, ptr, count) \
-  ((type*) srealloc((ptr),(count)*sizeof(type),__FILE__) )
-/*
-typedef struct { size_t size; void *ptr; } buffer;
-
-static void buffer_init_(buffer *b, size_t size, const char *file) MAYBE_UNUSED;
-static void buffer_init_(buffer *b, size_t size, const char *file)
-{
-  b->size=size, b->ptr=smalloc(size,file);
-}
-static void buffer_reserve_(buffer *b, size_t min, const char *file)
-  MAYBE_UNUSED;
-static void buffer_reserve_(buffer *b, size_t min, const char *file)
-{
-  size_t size = b->size;
-  if(size<min) {
-    size+=size/2+1;
-    if(size<min) size=min;
-    b->ptr=srealloc(b->ptr,size,file);
-  }
-}
-static void buffer_free(buffer *b) MAYBE_UNUSED;
-static void buffer_free(buffer *b) { free(b->ptr); }
-
-#define buffer_init(b,size) buffer_init_(b,size,__FILE__)
-#define buffer_reserve(b,min) buffer_reserve_(b,min,__FILE__)
-*/
-#endif
-

diff --git a/src/moab/point_locater/lotte/extrafindpt.h b/src/moab/point_locater/lotte/extrafindpt.h
deleted file mode 100644
index 38aa1a1..0000000
--- a/src/moab/point_locater/lotte/extrafindpt.h
+++ /dev/null
@@ -1,77 +0,0 @@
-#ifndef EXTRA_FINDPT_H
-#define EXTRA_FINDPT_H
-/* extra stuff that james didn't expose */
-
-typedef struct {
-  unsigned constraints;
-  unsigned dn, d1, d2;
-  real *x[3], *fdn[3];
-} opt_face_data_3;
-
-typedef struct {
-  unsigned constraints;
-  unsigned de, d1, d2;
-  real *x[3], *fd1[3], *fd2[3];
-} opt_edge_data_3;
-
-typedef struct {
-  unsigned constraints;
-  real x[3], jac[9];
-} opt_point_data_3;
-
-typedef struct {
-  lagrange_data *ld;
-  unsigned size[4];
-  const real *elx[3];
-  opt_face_data_3 fd;
-  opt_edge_data_3 ed;
-  opt_point_data_3 pd;
-  real *work;
-  real x[3], jac[9];
-} opt_data_3;
-
-
-void opt_alloc_3(opt_data_3 *p, lagrange_data *ld);
-void opt_free_3(opt_data_3 *p);
-double opt_findpt_3(opt_data_3 *p, const real *const elx[3],
-                           const real xstar[3], real r[3], unsigned *constr);
-void opt_vol_set_intp_3(opt_data_3 *p, const real r[3]);
-
-const unsigned opt_no_constraints_2 = 3+1;
-const unsigned opt_no_constraints_3 = 9+3+1;
-
-/* for 2d spectralQuad */
-/*--------------------------------------------------------------------------
-
-   2 - D
-
-  --------------------------------------------------------------------------*/
-
-typedef struct {
-  unsigned constraints;
-  unsigned de, d1;
-  real *x[2], *fd1[2];
-} opt_edge_data_2;
-
-typedef struct {
-  unsigned constraints;
-  real x[2], jac[4];
-} opt_point_data_2;
-
-typedef struct {
-  lagrange_data *ld;
-  unsigned size[3];
-  const real *elx[2];
-  opt_edge_data_2 ed;
-  opt_point_data_2 pd;
-  real *work;
-  real x[2], jac[4];
-} opt_data_2;
-void opt_alloc_2(opt_data_2 *p, lagrange_data *ld);
-void opt_free_2(opt_data_2 *p);
-double opt_findpt_2(opt_data_2 *p, const real *const elx[2],
-                           const real xstar[2], real r[2], unsigned *constr);
-
-
-
-#endif /*EXTRA_FINDPT_H */

diff --git a/src/moab/point_locater/lotte/findpt.h b/src/moab/point_locater/lotte/findpt.h
deleted file mode 100644
index 477e49e..0000000
--- a/src/moab/point_locater/lotte/findpt.h
+++ /dev/null
@@ -1,67 +0,0 @@
-#ifndef FINDPT_H
-#define FINDPT_H
-
-/* requires "types.h", "poly.h", "tensor.h" */
-#if !defined(TYPES_H) || !defined(POLY_H) || !defined(TENSOR_H)
-#warning "findpt.h" requires "types.h", "poly.h", "tensor.h"
-#endif
-
-typedef struct {
-  const real *xw[2];   /* geometry data */
-  real *z[2];          /* lobatto nodes */
-  lagrange_data ld[2]; /* interpolation, derivative weights & data */
-  unsigned nptel;      /* nodes per element */
-  struct findpt_hash_data_2 *hash;   /* geometric hashing data */
-  struct findpt_listel *list, **sorted, **end;
-                                        /* pre-allocated list of elements to
-                                           check (found by hashing), and
-                                           pre-allocated list of pointers into
-                                           the first list for sorting */
-  struct findpt_opt_data_2 *od; /* data for the optimization algorithm */
-  real *od_work;
-} findpt_data_2;
-
-typedef struct {
-  const real *xw[3];   /* geometry data */
-  real *z[3];          /* lobatto nodes */
-  lagrange_data ld[3]; /* interpolation, derivative weights & data */
-  unsigned nptel;      /* nodes per element */
-  struct findpt_hash_data_3 *hash;   /* geometric hashing data */
-  struct findpt_listel *list, **sorted, **end;
-                                        /* pre-allocated list of elements to
-                                           check (found by hashing), and
-                                           pre-allocated list of pointers into
-                                           the first list for sorting */
-  struct findpt_opt_data_3 *od; /* data for the optimization algorithm */
-  real *od_work;
-} findpt_data_3;
-
-findpt_data_2 *findpt_setup_2(
-          const real *const xw[2], const unsigned n[2], uint nel,
-          uint max_hash_size, real bbox_tol);
-findpt_data_3 *findpt_setup_3(
-          const real *const xw[3], const unsigned n[3], uint nel,
-          uint max_hash_size, real bbox_tol);
-
-void findpt_free_2(findpt_data_2 *p);
-void findpt_free_3(findpt_data_3 *p);
-
-const real *findpt_allbnd_2(const findpt_data_2 *p);
-const real *findpt_allbnd_3(const findpt_data_3 *p);
-
-typedef int (*findpt_func)(void *, const real *, int, uint *, real *, real *);
-int findpt_2(findpt_data_2 *p, const real x[2], int guess,
-             uint *el, real r[2], real *dist);
-int findpt_3(findpt_data_3 *p, const real x[3], int guess,
-             uint *el, real r[3], real *dist);
-
-void findpt_weights_2(findpt_data_2 *p, const real r[2]) ;
-
-void findpt_weights_3(findpt_data_3 *p, const real r[3]);
-
-double findpt_eval_2(findpt_data_2 *p, const real *u);
-
-double findpt_eval_3(findpt_data_3 *p, const real *u);
-
-#endif
-

diff --git a/src/moab/point_locater/lotte/minmax.h b/src/moab/point_locater/lotte/minmax.h
deleted file mode 100644
index 9fb5ed1..0000000
--- a/src/moab/point_locater/lotte/minmax.h
+++ /dev/null
@@ -1,82 +0,0 @@
-#ifndef MINMAX_H
-#define MINMAX_H
-
-/* requires <math.h> and "types.h" */
-
-#ifndef TYPES_H
-#warning "minmax.h" depends on "types.h"
-#endif
-
-/*--------------------------------------------------------------------------
-   Min, Max, Norm
-  --------------------------------------------------------------------------*/
-
-#ifdef __GNUC__
-#define MAYBE_UNUSED __attribute__ ((unused))
-#else
-#define MAYBE_UNUSED
-#endif
-
-#define DECLMINMAX(type, prefix) \
-  static type prefix##min_2(type a, type b) MAYBE_UNUSED;               \
-  static type prefix##min_2(type a, type b) {                           \
-    return b<a?b:a;                                                     \
-  }                                                                     \
-  static type prefix##max_2(type a, type b) MAYBE_UNUSED;               \
-  static type prefix##max_2(type a, type b) {                           \
-    return a>b?a:b;                                                     \
-  }                                                                     \
-  static void prefix##minmax_2(type *min, type *max, type a,            \
-                               type b) MAYBE_UNUSED;                    \
-  static void prefix##minmax_2(type *min, type *max, type a, type b) {  \
-    if(b<a) *min=b, *max=a;                                             \
-    else *min=a, *max=b;                                                \
-  }                                                                     \
-  static type prefix##min_3(type a, type b, type c) MAYBE_UNUSED;       \
-  static type prefix##min_3(type a, type b, type c) {                   \
-    return b<a?(c<b?c:b):(c<a?c:a);                                     \
-  }                                                                     \
-  static type prefix##max_3(type a, type b, type c) MAYBE_UNUSED;       \
-  static type prefix##max_3(type a, type b, type c) {                   \
-    return a>b?(a>c?a:c):(b>c?b:c);                                     \
-  }                                                                     \
-  static void prefix##minmax_3(type *min, type *max, type a, type b,    \
-                               type c) MAYBE_UNUSED;                    \
-  static void prefix##minmax_3(type *min, type *max, type a, type b,    \
-                               type c) {                                \
-    if(b<a) *min=prefix##min_2(b,c), *max=prefix##max_2(a,c);           \
-    else    *min=prefix##min_2(a,c), *max=prefix##max_2(b,c);           \
-  }
-
-DECLMINMAX(int, i)
-DECLMINMAX(unsigned, u)
-DECLMINMAX(real, r)
-#undef DECLMINMAX
-
-static real r1norm_1(real a) MAYBE_UNUSED;
-static real r1norm_1(real a) {
-  return fabsr(a);
-}
-static real r1norm_2(real a, real b) MAYBE_UNUSED;
-static real r1norm_2(real a, real b) {
-  return fabsr(a)+fabsr(b);
-}
-static real r1norm_3(real a, real b, real c) MAYBE_UNUSED;
-static real r1norm_3(real a, real b, real c) {
-  return fabsr(a)+fabsr(b)+fabsr(c);
-}
-static real r2norm_1(real a) MAYBE_UNUSED;
-static real r2norm_1(real a) {
-  return sqrtr(a*a);
-}
-static real r2norm_2(real a, real b) MAYBE_UNUSED;
-static real r2norm_2(real a, real b) {
-  return sqrtr(a*a+b*b);
-}
-static real r2norm_3(real a, real b, real c) MAYBE_UNUSED;
-static real r2norm_3(real a, real b, real c) {
-  return sqrtr(a*a+b*b+c*c);
-}
-
-#endif
-

diff --git a/src/moab/point_locater/lotte/poly.h b/src/moab/point_locater/lotte/poly.h
deleted file mode 100644
index ef3bf6c..0000000
--- a/src/moab/point_locater/lotte/poly.h
+++ /dev/null
@@ -1,155 +0,0 @@
-#ifndef POLY_H
-#define POLY_H
-
-/* requires "types.h" */
-#ifndef TYPES_H
-#warning "poly.h" requires "types.h"
-#endif
-
-/* 
-  For brevity's sake, some names have been shortened
-  Quadrature rules
-    Gauss   -> Gauss-Legendre quadrature (open)
-    Lobatto -> Gauss-Lobatto-Legendre quadrature (closed at both ends)
-  Polynomial bases
-    Legendre -> Legendre basis
-    Gauss    -> Lagrangian basis using Gauss   quadrature nodes
-    Lobatto  -> Lagrangian basis using Lobatto quadrature nodes
-*/
-
-/*--------------------------------------------------------------------------
-   Legendre Polynomial Matrix Computation
-   (compute P_i(x_j) for i = 0, ..., n and a given set of x)
-  --------------------------------------------------------------------------*/
-
-/* precondition: n >= 1
-   inner index is x index (0 ... m-1);
-   outer index is Legendre polynomial number (0 ... n)
- */
-void legendre_matrix(const real *x, int m, real *P, int n);
-
-/* precondition: n >= 1
-   inner index is Legendre polynomial number (0 ... n)
-   outer index is x index (0 ... m-1);
- */
-void legendre_matrix_t(const real *x, int m, real *P, int n);
-
-/* precondition: n >= 1
-   compute P_i(x) with i = 0 ... n
- */
-void legendre_row(real x, real *P, int n);
-
-
-/*--------------------------------------------------------------------------
-   Quadrature Nodes and Weights Calculation
-   
-   call the _nodes function before calling the _weights function
-  --------------------------------------------------------------------------*/
-
-void gauss_nodes(real *z, int n);   /* n nodes (order = 2n-1) */
-void lobatto_nodes(real *z, int n); /* n nodes (order = 2n-3) */
-
-void gauss_weights(const real *z, real *w, int n);
-void lobatto_weights(const real *z, real *w, int n);
-
-/*--------------------------------------------------------------------------
-   Lagrangian to Legendre Change-of-basis Matrix
-  --------------------------------------------------------------------------*/
-
-/* precondition: n >= 2
-   given the Gauss quadrature rule (z,w,n), compute the square matrix J
-   for transforming from the Gauss basis to the Legendre basis:
-   
-      u_legendre(i) = sum_j J(i,j) u_gauss(j)
-
-   computes J   = .5 (2i+1) w  P (z )
-             ij              j  i  j
-             
-   in column major format (inner index is i, the Legendre index)
- */
-void gauss_to_legendre(const real *z, const real *w, int n, real *J);
-
-/* precondition: n >= 2
-   same as above, but
-   in row major format (inner index is j, the Gauss index)
- */
-void gauss_to_legendre_t(const real *z, const real *w, int n, real *J);
-
-/* precondition: n >= 3
-   given the Lobatto quadrature rule (z,w,n), compute the square matrix J
-   for transforming from the Lobatto basis to the Legendre basis:
-   
-      u_legendre(i) = sum_j J(i,j) u_lobatto(j)
-
-   in column major format (inner index is i, the Legendre index)
- */
-void lobatto_to_legendre(const real *z, const real *w, int n, real *J);
-
-/*--------------------------------------------------------------------------
-   Lagrangian basis function evaluation
-  --------------------------------------------------------------------------*/
-
-/* given the Lagrangian nodes (z,n) and evaluation points (x,m)
-   evaluate all Lagrangian basis functions at all points x
-   
-   inner index of output J is the basis function index (row-major format)
-   provide work array with space for 4*n doubles
- */
-void lagrange_weights(const real *z, unsigned n,
-                      const real *x, unsigned m,
-                      real *J, real *work);
-
-/* given the Lagrangian nodes (z,n) and evaluation points (x,m)
-   evaluate all Lagrangian basis functions and their derivatives
-   
-   inner index of outputs J,D is the basis function index (row-major format)
-   provide work array with space for 6*n doubles
- */
-void lagrange_weights_deriv(const real *z, unsigned n,
-                            const real *x, unsigned m,
-                            real *J, real *D, real *work);
-
-/*--------------------------------------------------------------------------
-   Speedy Lagrangian Interpolation
-   
-   Usage:
-   
-     lagrange_data p;
-     lagrange_setup(&p,z,n);    *  setup for nodes z[0 ... n-1] *
-     
-     the weights
-       p->J [0 ... n-1]     interpolation weights
-       p->D [0 ... n-1]     1st derivative weights
-       p->D2[0 ... n-1]     2nd derivative weights
-     are computed for a given x with:
-       lagrange_0(p,x);  *  compute p->J *
-       lagrange_1(p,x);  *  compute p->J, p->D *
-       lagrange_2(p,x);  *  compute p->J, p->D, p->D2 *
-       lagrange_2u(p);   *  compute p->D2 after call of lagrange_1(p,x); *
-     These functions use the z array supplied to setup
-       (that pointer should not be freed between calls)
-     Weights for x=z[0] and x=z[n-1] are computed during setup; access as:
-       p->J_z0, etc. and p->J_zn, etc.
-
-     lagrange_free(&p);  *  deallocate memory allocated by setup *
-  --------------------------------------------------------------------------*/
-
-typedef struct {
-  unsigned n;                /* number of Lagrange nodes            */
-  const real *z;             /* Lagrange nodes (user-supplied)      */
-  real *J, *D, *D2;          /* weights for 0th,1st,2nd derivatives */
-  real *J_z0, *D_z0, *D2_z0; /* ditto at z[0]   (computed at setup) */
-  real *J_zn, *D_zn, *D2_zn; /* ditto at z[n-1] (computed at setup) */
-  real *w, *d, *u0, *v0, *u1, *v1, *u2, *v2; /* work data           */
-} lagrange_data;
-
-void lagrange_setup(lagrange_data *p, const real *z, unsigned n);
-void lagrange_free(lagrange_data *p);
-
-void lagrange_0(lagrange_data *p, real x) ;
-void lagrange_1(lagrange_data *p, real x) ;
-void lagrange_2(lagrange_data *p, real x) ;
-void lagrange_2u(lagrange_data *p) ;
-
-#endif
-

diff --git a/src/moab/point_locater/lotte/tensor.h b/src/moab/point_locater/lotte/tensor.h
deleted file mode 100644
index c5dd010..0000000
--- a/src/moab/point_locater/lotte/tensor.h
+++ /dev/null
@@ -1,102 +0,0 @@
-#ifndef TENSOR_H
-#define TENSOR_H
-
-/* requires "types.h" */
-
-#ifndef TYPES_H
-#warning "tensor.h" requires "types.h"
-#endif
-
-/*--------------------------------------------------------------------------
-   1-,2-,3-d Tensor Application
-   
-   the 3d case:
-   tensor_f3(R,mr,nr, S,ms,ns, T,mt,nt, u,v, work1,work2)
-     gives v = [ R (x) S (x) T ] u
-     where R is mr x nr, S is ms x ns, T is mt x nt,
-       each in row- or column-major format according to f := r | c
-     u is nr x ns x nt in column-major format (inner index is r)
-     v is mr x ms x mt in column-major format (inner index is r)
-  --------------------------------------------------------------------------*/
-
-void tensor_c1(const real *R, unsigned mr, unsigned nr, 
-               const real *u, real *v);
-void tensor_r1(const real *R, unsigned mr, unsigned nr, 
-               const real *u, real *v);
-
-/* work holds mr*ns reals */
-void tensor_c2(const real *R, unsigned mr, unsigned nr,
-               const real *S, unsigned ms, unsigned ns,
-               const real *u, real *v, real *work);
-void tensor_r2(const real *R, unsigned mr, unsigned nr,
-               const real *S, unsigned ms, unsigned ns,
-               const real *u, real *v, real *work);
-
-/* work1 holds mr*ns*nt reals,
-   work2 holds mr*ms*nt reals */
-void tensor_c3(const real *R, unsigned mr, unsigned nr,
-               const real *S, unsigned ms, unsigned ns,
-               const real *T, unsigned mt, unsigned nt,
-               const real *u, real *v, real *work1, real *work2);
-void tensor_r3(const real *R, unsigned mr, unsigned nr,
-               const real *S, unsigned ms, unsigned ns,
-               const real *T, unsigned mt, unsigned nt,
-               const real *u, real *v, real *work1, real *work2);
-
-/*--------------------------------------------------------------------------
-   1-,2-,3-d Tensor Application of Row Vectors (for Interpolation)
-   
-   the 3d case:
-   v = tensor_i3(Jr,nr, Js,ns, Jt,nt, u, work)
-   same effect as tensor_r3(Jr,1,nr, Js,1,ns, Jt,1,nt, u,&v, work1,work2):
-     gives v = [ Jr (x) Js (x) Jt ] u
-     where Jr, Js, Jt are row vectors (interpolation weights)
-     u is nr x ns x nt in column-major format (inner index is r)
-     v is a scalar
-  --------------------------------------------------------------------------*/
-
-real tensor_i1(const real *Jr, unsigned nr, const real *u);
-
-/* work holds ns reals */
-real tensor_i2(const real *Jr, unsigned nr,
-               const real *Js, unsigned ns,
-               const real *u, real *work);
-
-/* work holds ns*nt + nt reals */
-real tensor_i3(const real *Jr, unsigned nr,
-               const real *Js, unsigned ns,
-               const real *Jt, unsigned nt,
-               const real *u, real *work);
-
-/*--------------------------------------------------------------------------
-   1-,2-,3-d Tensor Application of Row Vectors
-             for simultaneous Interpolation and Gradient computation
-   
-   the 3d case:
-   v = tensor_ig3(Jr,Dr,nr, Js,Ds,ns, Jt,Dt,nt, u,g, work)
-     gives v   = [ Jr (x) Js (x) Jt ] u
-           g_0 = [ Dr (x) Js (x) Jt ] u
-           g_1 = [ Jr (x) Ds (x) Jt ] u
-           g_2 = [ Jr (x) Js (x) Dt ] u
-     where Jr,Dr,Js,Ds,Jt,Dt are row vectors
-       (interpolation & derivative weights)
-     u is nr x ns x nt in column-major format (inner index is r)
-     v is a scalar, g is an array of 3 reals
-  --------------------------------------------------------------------------*/
-
-real tensor_ig1(const real *Jr, const real *Dr, unsigned nr,
-                const real *u, real *g);
-
-/* work holds 2*ns reals */
-real tensor_ig2(const real *Jr, const real *Dr, unsigned nr,
-                const real *Js, const real *Ds, unsigned ns,
-                const real *u, real *g, real *work);
-
-/* work holds 2*ns*nt + 3*ns reals */
-real tensor_ig3(const real *Jr, const real *Dr, unsigned nr,
-                const real *Js, const real *Ds, unsigned ns,
-                const real *Jt, const real *Dt, unsigned nt,
-                const real *u, real *g, real *work);
-
-#endif
-

diff --git a/src/moab/point_locater/lotte/types.h b/src/moab/point_locater/lotte/types.h
deleted file mode 100644
index c17018e..0000000
--- a/src/moab/point_locater/lotte/types.h
+++ /dev/null
@@ -1,77 +0,0 @@
-#ifndef TYPES_H
-#define TYPES_H
-#include "float.h"
-
-/* integer type to use for everything */
-#if   defined(USE_LONG)
-#  define INTEGER long
-#elif defined(USE_LONG_LONG)
-#  define INTEGER long long
-#elif defined(USE_SHORT)
-#  define INTEGER short
-#else
-#  define INTEGER int
-#endif
-
-/* when defined, use the given type for global indices instead of INTEGER */
-#if   defined(USE_GLOBAL_LONG_LONG)
-#  define GLOBAL_INT long long
-#elif defined(USE_GLOBAL_LONG)
-#  define GLOBAL_INT long
-#else
-#  define GLOBAL_INT long
-#endif
-
-/* floating point type to use for everything */
-#if   defined(USE_FLOAT)
-   typedef float real;
-#  define floorr floorf
-#  define ceilr  ceilf
-#  define sqrtr  sqrtf
-#  define fabsr  fabsf
-#  define cosr   cosf
-#  define sinr   sinf
-#  define EPS   (128*FLT_EPSILON)
-#  define PI 3.1415926535897932384626433832795028841971693993751058209749445923F
-#elif defined(USE_LONG_DOUBLE)
-   typedef long double real;
-#  define floorr floorl
-#  define ceilr  ceill
-#  define sqrtr  sqrtl
-#  define fabsr  fabsl
-#  define cosr   cosl
-#  define sinr   sinl
-#  define EPS   (128*LDBL_EPSILON)
-#  define PI 3.1415926535897932384626433832795028841971693993751058209749445923L
-#else
-   typedef double real;
-#  define floorr floor
-#  define ceilr  ceil
-#  define sqrtr  sqrt
-#  define fabsr  fabs
-#  define cosr   cos
-#  define sinr   sin
-#  define EPS   (128*DBL_EPSILON)
-#  define PI 3.1415926535897932384626433832795028841971693993751058209749445923
-#endif
-
-/* apparently uint and ulong can be defined already in standard headers */
-#define uint uint_
-#define ulong ulong_
-#define sint sint_
-#define slong slong_
-
-typedef   signed INTEGER sint;
-typedef unsigned INTEGER uint;
-#undef INTEGER
-
-#ifdef GLOBAL_INT
-  typedef   signed GLOBAL_INT slong;
-  typedef unsigned GLOBAL_INT ulong;
-#else
-  typedef sint slong;
-  typedef uint ulong;
-#endif
-
-#endif
-

diff --git a/tools/mbcoupler/Coupler.cpp b/tools/mbcoupler/Coupler.cpp
index 6be6b8b..71231b8 100644
--- a/tools/mbcoupler/Coupler.cpp
+++ b/tools/mbcoupler/Coupler.cpp
@@ -11,11 +11,6 @@
 #include <algorithm>
 #include <sstream>
 
-//extern "C" 
-//{
-  //#include "minmax.h"
-  //}
-
 #include "assert.h"
 
 #define ERROR(a) {if (iBase_SUCCESS != err) std::cerr << a << std::endl;}

diff --git a/tools/mbcoupler/ElemUtil.cpp b/tools/mbcoupler/ElemUtil.cpp
index 96d4d66..cfc36e0 100644
--- a/tools/mbcoupler/ElemUtil.cpp
+++ b/tools/mbcoupler/ElemUtil.cpp
@@ -3,7 +3,6 @@
 #include <assert.h>
 
 #include "ElemUtil.hpp"
-#include "moab/FindPtFuncs.h"
 
 namespace moab {
 namespace ElemUtil {

diff --git a/tools/mbcoupler/ElemUtil.hpp b/tools/mbcoupler/ElemUtil.hpp
index c05dd5a..1db4c9e 100644
--- a/tools/mbcoupler/ElemUtil.hpp
+++ b/tools/mbcoupler/ElemUtil.hpp
@@ -7,8 +7,9 @@
 
 // to access data structures for spectral elements
 
-extern "C"{
-#include "moab/FindPtFuncs.h"    
+extern "C" 
+{
+#include "moab/FindPtFuncs.h"
 }
 
 namespace moab {

diff --git a/tools/mbcoupler/findpt_test.cpp b/tools/mbcoupler/findpt_test.cpp
index 3c29857..f92a668 100644
--- a/tools/mbcoupler/findpt_test.cpp
+++ b/tools/mbcoupler/findpt_test.cpp
@@ -6,8 +6,7 @@ using namespace moab;
 using namespace Element;
 
 extern "C"{
-#include "errmem.h" //for tmalloc, convenient but not C++
-#include "types.h"
+#include "moab/FindPtFuncs.h"
 }
 
 

diff --git a/tools/mbcoupler/ssn_test.cpp b/tools/mbcoupler/ssn_test.cpp
index 16d3fe4..21adf72 100644
--- a/tools/mbcoupler/ssn_test.cpp
+++ b/tools/mbcoupler/ssn_test.cpp
@@ -13,12 +13,10 @@
 #include <sstream>
 #include <cstring>
 #include <cstdlib>
-
 extern "C" 
 {
 #include "moab/FindPtFuncs.h"
 }
-
 #include "moab/TupleList.hpp"
 #include "moab/gs.hpp"
 #include "moab/Types.hpp"

diff --git a/tools/point_search.cpp b/tools/point_search.cpp
index 63b272e..97cfdf2 100644
--- a/tools/point_search.cpp
+++ b/tools/point_search.cpp
@@ -14,6 +14,11 @@
  */
 
 //Point Locater
+extern "C" 
+{
+#include "moab/FindPtFuncs.h"
+}
+
 #include "moab/point_locater/point_locater.hpp"
 #include "moab/point_locater/io.hpp"
 #include "moab/point_locater/tree/element_tree.hpp"


https://bitbucket.org/fathomteam/moab/commits/f0c081fb2f04/
Changeset:   f0c081fb2f04
Branch:      None
User:        tautges
Date:        2013-09-13 22:23:56
Summary:     in examples/, point_in_elem_search.cpp, makefile: compile errors fixed
Makefile.am: removing include of (removed) lotte subdir
BVHTree.hpp: fixing comments (thanks Danqing)
TreeTravStats.hpp, findpt_test.cpp: removed
ElementTest.cpp: cosmetic changes to remove them from diffs wrt upstream

Affected #:  7 files

diff --git a/examples/makefile b/examples/makefile
index 3b848d2..ff5876c 100644
--- a/examples/makefile
+++ b/examples/makefile
@@ -47,6 +47,9 @@ HelloParMOAB: HelloParMOAB.o
 TestExodusII: TestExodusII.o
 	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK}
 
+point_in_elem_search: point_in_elem_search.o
+	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK}
+
 clean:
 	rm -rf *.o ${EXAMPLES} ${PAREXAMPLES} ${EXOIIEXAMPLES}
 

diff --git a/examples/point_in_elem_search.cpp b/examples/point_in_elem_search.cpp
index 3cc16d1..a4f5619 100644
--- a/examples/point_in_elem_search.cpp
+++ b/examples/point_in_elem_search.cpp
@@ -7,15 +7,21 @@
 
 #include <iostream>
 #include <cstdlib>
+#include <cstdio>
 
 #include "moab/Core.hpp"
 #include "moab/Interface.hpp"
 #include "moab/Range.hpp"
+#include "moab/AdaptiveKDTree.hpp"
+#include "moab/ElemEvaluator.hpp"
+#include "moab/LinearHex.hpp"
+#include "moab/CN.hpp"
+#include "moab/SpatialLocator.hpp"
 
 using namespace moab;
 
 #define ERR(s) if (MB_SUCCESS != rval) \
-    {std::string str;mb->get_last_error(str); std::cerr << s << str << std::endl; return 1;}
+    {std::string str;mb.get_last_error(str); std::cerr << s << str << std::endl; return 1;}
 
 int main(int argc, char **argv) {
 
@@ -25,56 +31,52 @@ int main(int argc, char **argv) {
     std::cout << "Usage: " << argv[0] << "<filename> [num_queries]" << std::endl;
     return 0;
   }
-  else if (argc == 3) sscanf(argv[2], "%d", num_queries);
+  else if (argc == 3) num_queries = atoi(argv[2]);
 
     // instantiate & load a file
-  moab::Interface *mb = new moab::Core();
+  moab::Core mb;
 
-  Error err;
-  ErrorCode rval = mb->query_interface(err);
-  if (MB_SUCCESS != rval) return 1;
-  
     // load the file
-  rval = mb->load_file(argv[argc-1]); ERR("Error loading file");
+  ErrorCode rval = mb.load_file(argv[argc-1]); ERR("Error loading file");
   
     // get all 3d elements in the file
   Range elems;
-  rval = mb->get_entities_by_dimension(0, 3, elems); ERR("Error getting 3d elements");
+  rval = mb.get_entities_by_dimension(0, 3, elems); ERR("Error getting 3d elements");
   
     // create a tree to use for the location service
-  AdaptiveKDTree tree(mb);
+  AdaptiveKDTree tree(&mb);
 
     // specify an evaluator based on linear hexes
-  ElemEvaluator el_eval(mb, LinearHex::get_eval_set());
+  ElemEvaluator el_eval(&mb);
 
     // build the SpatialLocator
-  SpatialLocator sl(mb, elems, &tree, &el_eval);
+  SpatialLocator sl(&mb, elems, &tree);
   
     // get the box extents
-  CartVect box_min, box_max, box_extents, pos;
-  rval = sl.get_bounding_box(box_min, box_max); ERR("Problem getting tree bounding box");
-  box_extents = box_max - box_min;
+  BoundBox box;
+  CartVect box_extents, pos;
+  rval = sl.get_bounding_box(box); ERR("Problem getting tree bounding box");
+  box_extents = box.bMax - box.bMin;
   
     // query at random places in the tree
-  EntityHandle elem;
   CartVect params;
   bool is_inside;
   int num_inside = 0;
+  EntityHandle elem;
   for (int i = 0; i < num_queries; i++) {
-    pos = box_min + 
+    pos = box.bMin + 
         CartVect(box_extents[0]*.01*(rand()%100), box_extents[1]*.01*(rand()%100), box_extents[2]*.01*(rand()%100));
-    
-    ErrorCode tmp_rval = sl.locate_point(pos, tol, in_elem, params, &is_inside);
+    ErrorCode tmp_rval = sl.locate_point(pos.array(), elem, params.array(), 0.0, 0.0, &is_inside);
     if (MB_SUCCESS != tmp_rval) rval = tmp_rval;
     if (is_inside) num_inside++;
   }
   
   std::cout << "Mesh contains " << elems.size() << " elements of type " 
-            << CN::EntityTypeName(mb->type_from_handle(*elems.begin())) << std::endl;
-  std::cout << "Bounding box min-max = (" << box_min[0] << "," << box_min[1] << "," << box_min[2] << ")-("
-            << box_max[0] << "," << box_max[1] << "," << box_max[2] << ")" << std::endl;
+            << CN::EntityTypeName(mb.type_from_handle(*elems.begin())) << std::endl;
+  std::cout << "Bounding box min-max = (" << box.bMin[0] << "," << box.bMin[1] << "," << box.bMin[2] << ")-("
+            << box.bMax[0] << "," << box.bMax[1] << "," << box.bMax[2] << ")" << std::endl;
   std::cout << "Queries inside box = " << num_inside << "/" << num_queries << " = " 
-            << (double)(num_inside/num_queries) << "%" << std::endl;
+            << ((double)num_inside)/num_queries << "%" << std::endl;
 }
 
     

diff --git a/src/Makefile.am b/src/Makefile.am
index 5f59ff3..761f704 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -23,7 +23,6 @@ AM_CPPFLAGS += -DIS_BUILDING_MB \
                -I$(srcdir)/io \
                -I$(srcdir)/io/mhdf/include \
                -I$(srcdir)/parallel \
-	       -I$(srcdir)/moab/point_locater/lotte \
                -I$(srcdir)/LocalDiscretization
 
 # The directory in which to install headers

diff --git a/src/moab/BVHTree.hpp b/src/moab/BVHTree.hpp
index f80462d..7f0c7ec 100644
--- a/src/moab/BVHTree.hpp
+++ b/src/moab/BVHTree.hpp
@@ -94,13 +94,13 @@ namespace moab {
          * If params_out is non-NULL and myEval is non-NULL, will evaluate individual entities
          * in tree nodes and return containing entities in leaves_out.  In those cases, if params_out
          * is also non-NULL, will return parameters in those elements in that vector.
-         * \param point Point to be located in tree
+         * \param from_point Point to be located in tree
          * \param distance Distance within which to query
-         * \param leaves_out Leaves within distance or containing point
+         * \param result_list Leaves within distance or containing point
          * \param tol Tolerance below which a point is "in"
-         * \param dists_out If non-NULL, will contain distsances to leaves
-         * \param params_out If non-NULL, will contain parameters of the point in the ents in leaves_out
-         * \param start_node Start from this tree node (non-NULL) instead of tree root (NULL)
+         * \param result_dists If non-NULL, will contain distsances to leaves
+         * \param result_params If non-NULL, will contain parameters of the point in the ents in leaves_out
+         * \param tree_root Start from this tree node (non-NULL) instead of tree root (NULL)
          */
       virtual ErrorCode distance_search(const double from_point[3],
                                         const double distance,

diff --git a/src/moab/TreeTravStats.hpp b/src/moab/TreeTravStats.hpp
deleted file mode 100644
index e69de29..0000000

diff --git a/tools/mbcoupler/ElementTest.cpp b/tools/mbcoupler/ElementTest.cpp
index f48ec82..4f37602 100644
--- a/tools/mbcoupler/ElementTest.cpp
+++ b/tools/mbcoupler/ElementTest.cpp
@@ -138,8 +138,7 @@ void test_spectral_hex()
      // first evaluate a point, then inverse it to see if we get the same thing
      moab::CartVect rst(0.1, -0.1, 0.5);
      moab::CartVect pos = specHex.evaluate(rst);
-     moab::CartVect inverse;
-     inverse = specHex.ievaluate(pos);
+     moab::CartVect inverse = specHex.ievaluate(pos);
      std::cout << "difference" << rst-inverse << "\n";
      Matrix3 jac=specHex.jacobian(rst);
      std::cout<< "jacobian: \n" << jac << " \n determinant: " << jac.determinant() << "\n";
@@ -211,7 +210,7 @@ void test_spectral_quad()
     }
 
 
-    specQuad.set_vertices(verts);
+     specQuad.set_vertices(verts);
      specQuad.compute_gl_positions();
      // do something with the gl positions, project them on a sphere, and create another mesh?
      if (rit==ents.begin())

diff --git a/tools/mbcoupler/findpt_test.cpp b/tools/mbcoupler/findpt_test.cpp
deleted file mode 100644
index f92a668..0000000
--- a/tools/mbcoupler/findpt_test.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-#include <iostream>
-#include "ElemUtil.hpp"
-
-using namespace std;
-using namespace moab;
-using namespace Element;
-
-extern "C"{
-#include "moab/FindPtFuncs.h"
-}
-
-
-void test_hex_findpt()
-{
-
-    CartVect xyz(.5,.3,.4);
-    CartVect rst;
-    double dist;
-
-    double *xm[3]; //element coord fields, lex ordering
-    const int n=5; //number of nodes per direction (min is 2, for linear element)
-
-    for(int d=0; d<3; d++){
-      xm[d]=tmalloc(double, n*n*n);
-    }
-
-    double scale = 1./(n-1);
-    int node = 0;
-    //Stuff xm with sample data
-    for(int k=0; k<n; k++){
-      for(int j=0; j<n; j++){
-        for(int i=0; i<n; i++){
-
-          xm[0][node] = i*scale; 
-          xm[1][node] = j*scale;
-          xm[2][node] = k*scale;
-          
-          node++;
-        }
-      }
-    }
-        
-    hex_findpt(xm, n, xyz, rst, dist);
-
-
-    cout << "Coords of " << xyz << " are:  "<< rst <<
-      " distance: "<< dist << endl;
-
-}
-
-
-
-void test_hex_eval()
-{
-    CartVect rst(.5,.3,.4);
-    double value;
-
-    const int n=2; //number of nodes per direction (min is 2, for linear element)
-    double *field = tmalloc(double, n*n*n);
-
-    double scale = 1./(n-1);
-    int node = 0;
-
-    //Stuff field with sample data
-    for(int k=0; k<n; k++){
-      for(int j=0; j<n; j++){
-        for(int i=0; i<n; i++){
-          field[node] = 100*scale*(i); 
-          node++;
-        }
-      }
-    }
-        
-    hex_eval(field, n, rst, value);
-    cout << "Value at " << rst << "is: " << value << endl;
-}
-
-
-
-void test_nat_coords_trilinear_hex2()
-{
-  CartVect hex[8];
-  CartVect xyz(.5,.3,.4);
-  CartVect ncoords;;
-  double etol;
-  
-  //Make our sample hex the unit cube [0,1]**3
-  hex[0] = CartVect(0,0,0);
-  hex[1] = CartVect(1,0,0);
-  hex[2] = CartVect(1,1,0);
-  hex[3] = CartVect(0,1,0);
-  hex[4] = CartVect(0,0,1);
-  hex[5] = CartVect(1,0,1);
-  hex[6] = CartVect(1,1,1);
-  hex[7] = CartVect(0,1,1);
-
-  etol = .1 ; //ignored by nat_coords
-
-  nat_coords_trilinear_hex2(hex, xyz, ncoords, etol);
-      
-  cout << "Coords of " << xyz << " are:  "<< ncoords << endl;
-
-}
-
-
-
-int main(){
-  test_nat_coords_trilinear_hex2();
-  test_hex_findpt();
-  test_hex_eval();
-}


https://bitbucket.org/fathomteam/moab/commits/c4376983de0b/
Changeset:   c4376983de0b
Branch:      None
User:        tautges
Date:        2013-09-13 22:25:55
Summary:     Merge branch 'master' of https://bitbucket.org/fathomteam/moab

Conflicts:
	src/moab/Core.hpp
	test/Makefile.am
	test/test_boundbox.cpp

(fixed conflicts)

Affected #:  5 files

diff --git a/src/Makefile.am b/src/Makefile.am
index 761f704..dc0c3f2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -163,6 +163,7 @@ nobase_libMOAB_la_include_HEADERS = \
   moab/EntityHandle.hpp \
   moab/FBEngine.hpp \
   moab/FileOptions.hpp \
+  moab/FindPtFuncs.h \
   moab/Forward.hpp \
   moab/GeomUtil.hpp \
   moab/Interface.hpp \

diff --git a/src/moab/Core.hpp b/src/moab/Core.hpp
index 09c0b13..aa7d9da 100644
--- a/src/moab/Core.hpp
+++ b/src/moab/Core.hpp
@@ -216,16 +216,17 @@ public:
   
       //! Gets the connectivity for an element EntityHandle. 
       /** For non-element handles (ie, MeshSets), 
-          returns an error. Connectivity data is copied from the database into the vector 
-          <em>connectivity</em>. The nodes in <em>connectivity</em> are properly ordered.
-          \param entity_handle EntityHandle to get connectivity of.
-          \param connectivity Vector in which connectivity of <em>entity_handle</em> is returned.  
-          Should contain MeshVertices.
-          \param corners_only If true, returns only corner vertices, otherwise returns all of them (including any higher-order vertices)
-
-          Example: \code 
-          std::vector<EntityHandle> conn;
-          get_connectivity( entity_handle, conn ); \endcode */
+       * returns an error. Connectivity data is copied from the database into the vector 
+       *   <em>connectivity</em>. The nodes in <em>connectivity</em> are properly ordered.
+       *  \param entity_handle EntityHandle to get connectivity of.
+       *  \param connectivity Vector in which connectivity of <em>entity_handle</em> is returned.  
+       *   Should contain MeshVertices.
+       *  \param corners_only If true, returns only corner vertices, otherwise returns all of them (including any higher-order vertices)
+       *
+       *   Example: \code 
+       *   std::vector<EntityHandle> conn;
+       *   get_connectivity( entity_handle, conn ); \endcode 
+       */
     virtual ErrorCode  get_connectivity(const EntityHandle *entity_handles, 
                                         const int num_handles,
                                         std::vector<EntityHandle> &connectivity, 

diff --git a/test/Makefile.am b/test/Makefile.am
index d65497c..e4b7909 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -144,6 +144,8 @@ kd_tree_test_CPPFLAGS = $(AM_CPPFLAGS) $(CPPFLAGS)
 coords_connect_iterate_SOURCES = coords_connect_iterate.cpp
 coords_connect_iterate_CPPFLAGS = $(AM_CPPFLAGS) $(CPPFLAGS)
 
+test_boundbox_SOURCES = test_boundbox.cpp
+
 if PARALLEL
 moab_test_CPPFLAGS += -I$(top_srcdir)/src/parallel
 kd_tree_test_CPPFLAGS += -I$(top_srcdir)/src/parallel

diff --git a/test/test_boundbox.cpp b/test/test_boundbox.cpp
index d3c8c3d..9fe0357 100644
--- a/test/test_boundbox.cpp
+++ b/test/test_boundbox.cpp
@@ -90,7 +90,7 @@ void test_bound_box()
   double diagsq = box.diagonal_squared();
   CHECK_REAL_EQUAL(diagsq, 192.0, tol);
   double diag = box.diagonal_length();
-  CHECK_REAL_EQUAL(diag, sqrt(3)*8.0, tol);
+  CHECK_REAL_EQUAL(diag, sqrt(3.0)*8.0, tol);
   
     // check distance function
 

diff --git a/tools/dagmc/cub2h5m.cc b/tools/dagmc/cub2h5m.cc
index 535a689..f9ec41b 100644
--- a/tools/dagmc/cub2h5m.cc
+++ b/tools/dagmc/cub2h5m.cc
@@ -4,7 +4,7 @@
 #include "moab/CN.hpp"
 #include "moab/Core.hpp"
 #include "moab/CartVect.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "moab/Skinner.hpp"
 #include "quads_to_tris.hpp"
 #include "DagMC.hpp"


https://bitbucket.org/fathomteam/moab/commits/c813332c936e/
Changeset:   c813332c936e
Branch:      None
User:        tautges
Date:        2013-09-14 00:27:13
Summary:     Some fixes for mbcslam, now things compile, but spec_visu_test fails.

Affected #:  2 files

diff --git a/tools/mbcslam/Intx2Mesh.cpp b/tools/mbcslam/Intx2Mesh.cpp
index 6ddadfb..40f85ee 100644
--- a/tools/mbcslam/Intx2Mesh.cpp
+++ b/tools/mbcslam/Intx2Mesh.cpp
@@ -13,6 +13,7 @@
 // this is for DBL_MAX
 #include <float.h>
 #include <queue>
+#include <sstream>
 #include "moab/GeomUtil.hpp"
 
 namespace moab {
@@ -421,25 +422,25 @@ ErrorCode Intx2Mesh::initialize_local_kdtree(EntityHandle euler_set)
   ErrorCode rval = mb->get_entities_by_dimension(euler_set, 2, local_ents);
   ERRORR(rval, "can't get ents by dimension");
 
-  AdaptiveKDTree::Settings settings;
-  settings.candidatePlaneSet = AdaptiveKDTree::SUBDIVISION;
-
     //get entities on the local part
   ErrorCode result = MB_SUCCESS;
 
-
       // build the tree for local processor
   int numIts = 3;
+  int max_per_leaf = 6;
   for (int i = 0; i < numIts; i++) {
+    std::ostringstream ostr;
+    ostr << "CANDIDATE_PLANE_SET=SUBDIVISION;MAX_PER_LEAF=" << max_per_leaf;
+    FileOptions opts(ostr.str().c_str());
     myTree = new AdaptiveKDTree(mb);
-    result = myTree->build_tree(local_ents, localRoot, &settings);
+    result = myTree->build_tree(local_ents, &localRoot, &opts);
     if (MB_SUCCESS != result) {
       std::cout << "Problems building tree";
       if (numIts != i) {
         delete myTree;
-        settings.maxEntPerLeaf *= 2;
+        max_per_leaf *= 2;
         std::cout << "; increasing elements/leaf to "
-                  << settings.maxEntPerLeaf << std::endl;;
+                  << max_per_leaf << std::endl;;
       }
       else {
         std::cout << "; exiting" << std::endl;
@@ -455,8 +456,11 @@ ErrorCode Intx2Mesh::initialize_local_kdtree(EntityHandle euler_set)
     allBoxes.resize(6*parcomm->proc_config().proc_size());
   else allBoxes.resize(6);
   my_rank = (parcomm ? parcomm->proc_config().proc_rank() : 0);
-  result = myTree->get_tree_box(localRoot, &allBoxes[6*my_rank], &allBoxes[6*my_rank+3]);
+  BoundBox box;
+  result = myTree->get_bounding_box(box);
   if (MB_SUCCESS != result) return result;
+  box.bMin.get(&allBoxes[6*my_rank]);
+  box.bMax.get(&allBoxes[6*my_rank+3]);
 
     // now communicate to get all boxes
     // use "in place" option
@@ -757,34 +761,29 @@ ErrorCode Intx2Mesh::test_local_box(double *xyz,
 ErrorCode Intx2Mesh::inside_entities(double xyz[3],
                                  std::vector<EntityHandle> &entities)
 {
-  AdaptiveKDTreeIter treeiter;
-  ErrorCode result = myTree->get_tree_iterator(localRoot, treeiter);
-  if (MB_SUCCESS != result) {
-    std::cout << "Problems getting iterator" << std::endl;
-    return result;
-  }
-
   double epsilon = this->box_error;//1.e-10; try to get some close boxes, because of the
   // the curvature that can appear on a sphere
   std::vector<EntityHandle> leaves;
+  ErrorCode result;
   if (epsilon) {
     std::vector<double> dists;
 
-    result = myTree->leaves_within_distance(localRoot, xyz, epsilon, leaves, &dists);
+    result = myTree->distance_search(xyz, epsilon, leaves, 0.0, &dists);
     if (leaves.empty())
       // not found returns success here, with empty list, just like case with no epsilon
       return MB_SUCCESS;
 
   }
   else {
-    result = myTree->leaf_containing_point(localRoot, xyz, treeiter);
+    EntityHandle leaf;
+    result = myTree->point_search(xyz, leaf);
     if(MB_ENTITY_NOT_FOUND==result) //point is outside of myTree's bounding box
       return MB_SUCCESS;
     else if (MB_SUCCESS != result) {
       std::cout << "Problems getting leaf \n";
       return result;
     }
-    leaves.push_back(treeiter.handle());
+    leaves.push_back(leaf);
   }
 
   Range range_leaf;

diff --git a/tools/mbcslam/process_arm.cpp b/tools/mbcslam/process_arm.cpp
index 06472a9..da4c284 100644
--- a/tools/mbcslam/process_arm.cpp
+++ b/tools/mbcslam/process_arm.cpp
@@ -223,14 +223,14 @@ int main(int argc, char ** argv)
   mb.add_entities(newSet, nodes);
 
   // build a kd tree with the vertices
-  EntityHandle tree_root;
-  AdaptiveKDTree kd(&mb, true);
-  rval = kd.build_tree(nodes, tree_root);
+  EntityHandle tree_root = 0;
+  AdaptiveKDTree kd(&mb);
+  rval = kd.build_tree(nodes, &tree_root);
   if (MB_SUCCESS != rval)
     return 1;
 
   unsigned int  min_depth, max_depth;
-  rval = kd.depth(tree_root, min_depth, max_depth);
+  rval = kd.compute_depth(tree_root, min_depth, max_depth);
   if (MB_SUCCESS != rval)
      return 1;
   std::cout << "min_depth, max_depth " << min_depth << " " << max_depth << "\n";
@@ -270,10 +270,9 @@ int main(int argc, char ** argv)
   {
     CartVect pos(ptr); // take 3 coordinates
     std::vector<EntityHandle> leaves;
-    rval = kd.leaves_within_distance( tree_root,
-                                          ptr,
-                                          0.001,
-                                        leaves);
+    rval = kd.distance_search( ptr,
+                               0.001,
+                               leaves);
     if (MB_SUCCESS != rval)
       return 1;
     Range closeVerts;


https://bitbucket.org/fathomteam/moab/commits/2a988848649a/
Changeset:   2a988848649a
Branch:      None
User:        tautges
Date:        2013-09-16 17:00:47
Summary:     point_in_elem_search: multiplying by 100 for %
MergeMesh: adding passed in kd tree argument, for efficiency

Thanks Iulian/Danqing for comments.

Affected #:  4 files

diff --git a/examples/point_in_elem_search.cpp b/examples/point_in_elem_search.cpp
index a4f5619..a917fa0 100644
--- a/examples/point_in_elem_search.cpp
+++ b/examples/point_in_elem_search.cpp
@@ -76,7 +76,7 @@ int main(int argc, char **argv) {
   std::cout << "Bounding box min-max = (" << box.bMin[0] << "," << box.bMin[1] << "," << box.bMin[2] << ")-("
             << box.bMax[0] << "," << box.bMax[1] << "," << box.bMax[2] << ")" << std::endl;
   std::cout << "Queries inside box = " << num_inside << "/" << num_queries << " = " 
-            << ((double)num_inside)/num_queries << "%" << std::endl;
+            << 100.0*((double)num_inside)/num_queries << "%" << std::endl;
 }
 
     

diff --git a/src/MergeMesh.cpp b/src/MergeMesh.cpp
index 2ca8cd4..4cc8158 100644
--- a/src/MergeMesh.cpp
+++ b/src/MergeMesh.cpp
@@ -81,7 +81,7 @@ moab::ErrorCode MergeMesh::merge_entities(moab::Range &elems,
   if (moab::MB_SUCCESS != result) return result;
 
   // find matching vertices, mark them
-  result = find_merged_to(tree_root, mbMergeTag);
+  result = find_merged_to(tree_root, kd, mbMergeTag);
   if (moab::MB_SUCCESS != result) return result;
 
   // merge them if requested
@@ -125,10 +125,10 @@ moab::ErrorCode MergeMesh::perform_merge(moab::Tag merge_tag)
 }
 
 moab::ErrorCode MergeMesh::find_merged_to(moab::EntityHandle &tree_root, 
+                                          moab::AdaptiveKDTree &tree,
 					  moab::Tag merge_tag) 
 {
   moab::AdaptiveKDTreeIter iter;
-  moab::AdaptiveKDTree tree(mbImpl);
   
   // evaluate vertices in this leaf
   moab::Range leaf_range, leaf_range2;

diff --git a/src/moab/MergeMesh.hpp b/src/moab/MergeMesh.hpp
index f9359c9..489bb3e 100644
--- a/src/moab/MergeMesh.hpp
+++ b/src/moab/MergeMesh.hpp
@@ -6,6 +6,8 @@
 
 namespace moab {
 
+class AdaptiveKDTree;
+    
 class MergeMesh 
 {
 public:
@@ -49,6 +51,7 @@ private:
     //- given a kdtree, set tag on vertices in leaf nodes with vertices
     //- to which they should be merged
   moab::ErrorCode find_merged_to(moab::EntityHandle &tree_root,
+                                 moab::AdaptiveKDTree &tree,
 				 moab::Tag merged_to);
   
   moab::Interface *mbImpl;

diff --git a/test/adaptive_kd_tree_tests.cpp b/test/adaptive_kd_tree_tests.cpp
index eeaa04b..b1f2e22 100644
--- a/test/adaptive_kd_tree_tests.cpp
+++ b/test/adaptive_kd_tree_tests.cpp
@@ -11,6 +11,10 @@ using namespace moab;
 #include <algorithm>
 #include <sstream>
 
+#ifdef USE_MPI
+#include "moab_mpi.h"
+#endif
+
 /* Utility method - compare two range boxes */
 bool box_equal( const AdaptiveKDTreeIter& iter, 
                 double x_min, double y_min, double z_min,
@@ -1299,6 +1303,11 @@ void test_leaf_intersects_ray()
 
 int main()
 {
+#ifdef USE_MPI
+  int fail = MPI_Init(0, 0);
+  if (fail) return fail;
+#endif
+
   int error_count = 0;
   
   error_count += RUN_TEST(leaf_iterator_test);
@@ -1311,5 +1320,11 @@ int main()
   error_count += RUN_TEST(test_leaf_sibling);
   error_count += RUN_TEST(test_leaf_intersects_plane);
   error_count += RUN_TEST(test_leaf_intersects_ray);
+
+#ifdef USE_MPI
+  fail = MPI_Finalize();
+  if (fail) return fail;
+#endif
+
   return error_count;
 }


https://bitbucket.org/fathomteam/moab/commits/4cc677f93e4f/
Changeset:   4cc677f93e4f
Branch:      master
User:        tautges
Date:        2013-09-17 00:24:46
Summary:     Merged in tautges/moabcoupling (pull request #13)

Attempt #2 at pulling next-generation coupler back into master
Affected #:  60 files

diff --git a/configure.ac b/configure.ac
index b08389a..fd4062a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1184,6 +1184,7 @@ AC_CONFIG_FILES([Makefile
                  src/Makefile
                  src/io/Makefile
                  src/io/mhdf/Makefile
+		 src/LocalDiscretization/Makefile
                  src/parallel/Makefile
                  src/oldinc/Makefile
                  test/Makefile
@@ -1191,6 +1192,7 @@ AC_CONFIG_FILES([Makefile
                  test/dual/Makefile
                  test/obb/Makefile
                  test/perf/Makefile
+                 test/perf/point_location/Makefile
                  test/io/Makefile
                  test/parallel/Makefile
                  test/oldinc/Makefile

diff --git a/examples/makefile b/examples/makefile
index 3b848d2..ff5876c 100644
--- a/examples/makefile
+++ b/examples/makefile
@@ -47,6 +47,9 @@ HelloParMOAB: HelloParMOAB.o
 TestExodusII: TestExodusII.o
 	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK}
 
+point_in_elem_search: point_in_elem_search.o
+	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK}
+
 clean:
 	rm -rf *.o ${EXAMPLES} ${PAREXAMPLES} ${EXOIIEXAMPLES}
 

diff --git a/examples/old/Makefile.am b/examples/old/Makefile.am
index d0a33b9..21e6da3 100644
--- a/examples/old/Makefile.am
+++ b/examples/old/Makefile.am
@@ -7,7 +7,6 @@
 check_PROGRAMS = FileRead \
                  GeomSetHierarchy \
                  GetEntities \
-                 KDTree \
 		 ObbTree \
                  SetsNTags \
                  SkinMesh \
@@ -28,7 +27,6 @@ GetEntities_SOURCES = simple/GetEntities.cpp
 SetsNTags_SOURCES = SetsNTags.cpp
 SkinMesh_SOURCES = SkinMesh.cpp
 SurfArea_SOURCES = SurfArea.cpp
-KDTree_SOURCES = KDTree.cpp
 ObbTree_SOURCES = ObbTree.cpp
 
 exampledir = ${docdir}/examples
@@ -38,7 +36,6 @@ nobase_example_DATA = \
                GeomSetHierarchy.cpp \
                simple/GetEntities.cpp \
                simple/makefile \
-               KDTree.cpp \
 	       ObbTree.cpp \
                SetsNTags.cpp \
                SkinMesh.cpp \

diff --git a/examples/point_in_elem_search.cpp b/examples/point_in_elem_search.cpp
new file mode 100644
index 0000000..a917fa0
--- /dev/null
+++ b/examples/point_in_elem_search.cpp
@@ -0,0 +1,86 @@
+/** \brief This test shows how to perform local point-in-element searches with MOAB's new tree searching functionality.  
+ *
+ * MOAB's SpatialLocator functionality performs point-in-element searches over a local or parallel mesh.
+ * SpatialLocator is flexible as to what kind of tree is used and what kind of element basis functions are 
+ * used to localize elements and interpolate local fields.
+ */
+
+#include <iostream>
+#include <cstdlib>
+#include <cstdio>
+
+#include "moab/Core.hpp"
+#include "moab/Interface.hpp"
+#include "moab/Range.hpp"
+#include "moab/AdaptiveKDTree.hpp"
+#include "moab/ElemEvaluator.hpp"
+#include "moab/LinearHex.hpp"
+#include "moab/CN.hpp"
+#include "moab/SpatialLocator.hpp"
+
+using namespace moab;
+
+#define ERR(s) if (MB_SUCCESS != rval) \
+    {std::string str;mb.get_last_error(str); std::cerr << s << str << std::endl; return 1;}
+
+int main(int argc, char **argv) {
+
+  int num_queries = 1000000;
+  
+  if (argc == 1) {
+    std::cout << "Usage: " << argv[0] << "<filename> [num_queries]" << std::endl;
+    return 0;
+  }
+  else if (argc == 3) num_queries = atoi(argv[2]);
+
+    // instantiate & load a file
+  moab::Core mb;
+
+    // load the file
+  ErrorCode rval = mb.load_file(argv[argc-1]); ERR("Error loading file");
+  
+    // get all 3d elements in the file
+  Range elems;
+  rval = mb.get_entities_by_dimension(0, 3, elems); ERR("Error getting 3d elements");
+  
+    // create a tree to use for the location service
+  AdaptiveKDTree tree(&mb);
+
+    // specify an evaluator based on linear hexes
+  ElemEvaluator el_eval(&mb);
+
+    // build the SpatialLocator
+  SpatialLocator sl(&mb, elems, &tree);
+  
+    // get the box extents
+  BoundBox box;
+  CartVect box_extents, pos;
+  rval = sl.get_bounding_box(box); ERR("Problem getting tree bounding box");
+  box_extents = box.bMax - box.bMin;
+  
+    // query at random places in the tree
+  CartVect params;
+  bool is_inside;
+  int num_inside = 0;
+  EntityHandle elem;
+  for (int i = 0; i < num_queries; i++) {
+    pos = box.bMin + 
+        CartVect(box_extents[0]*.01*(rand()%100), box_extents[1]*.01*(rand()%100), box_extents[2]*.01*(rand()%100));
+    ErrorCode tmp_rval = sl.locate_point(pos.array(), elem, params.array(), 0.0, 0.0, &is_inside);
+    if (MB_SUCCESS != tmp_rval) rval = tmp_rval;
+    if (is_inside) num_inside++;
+  }
+  
+  std::cout << "Mesh contains " << elems.size() << " elements of type " 
+            << CN::EntityTypeName(mb.type_from_handle(*elems.begin())) << std::endl;
+  std::cout << "Bounding box min-max = (" << box.bMin[0] << "," << box.bMin[1] << "," << box.bMin[2] << ")-("
+            << box.bMax[0] << "," << box.bMax[1] << "," << box.bMax[2] << ")" << std::endl;
+  std::cout << "Queries inside box = " << num_inside << "/" << num_queries << " = " 
+            << 100.0*((double)num_inside)/num_queries << "%" << std::endl;
+}
+
+    
+  
+  
+  
+

This diff is so big that we needed to truncate the remainder.

Repository URL: https://bitbucket.org/fathomteam/moab/

--

This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.


More information about the moab-dev mailing list