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

commits-noreply at bitbucket.org commits-noreply at bitbucket.org
Mon Mar 17 12:42:27 CDT 2014


2 new commits in MOAB:

https://bitbucket.org/fathomteam/moab/commits/fa4d3ff0c3c9/
Changeset:   fa4d3ff0c3c9
Branch:      None
User:        tautges
Date:        2014-03-17 18:41:58
Summary:     AdaptiveKDTree, BVHTree: split some of the stats into separate initialization/traversal stats
TreeStats: add some stats on leaf node objects
ElemEvaluator: return MB_INDEX_NOT_FOUND instead of MB_FAILURE on failure to converge reverse evaluation test, allows applications to react differently to this type of failure.  Also, add some documentation of function args.
LinearTet: in reverse evaluation function, on failure to converge, return success if intermediate result is outside element; same thing is done in ElemEvaluator form of this funciton.
BVHTree: fix bug in decrement of unsigned possibly-zero variable.
TreeStats: separate output into init/traversal stats; also add leaf object details, and functionality in compute_stats to compute these quantities.

Affected #:  7 files

diff --git a/src/AdaptiveKDTree.cpp b/src/AdaptiveKDTree.cpp
index 8aafdd1..4b104b4 100644
--- a/src/AdaptiveKDTree.cpp
+++ b/src/AdaptiveKDTree.cpp
@@ -798,7 +798,7 @@ namespace moab {
                                             double& t_enter, 
                                             double& t_exit ) const
     {
-      treeTool->treeStats.leafObjectTests++;
+      treeTool->treeStats.traversalLeafObjectTests++;
       return GeomUtil::ray_box_intersect( CartVect(box_min()),
                                           CartVect(box_max()),
                                           CartVect(ray_point),
@@ -850,7 +850,7 @@ namespace moab {
   
         // vertices
       for (i = elems.begin(); i != elem_begin; ++i) {
-        tree_stats().leafObjectTests++;
+        tree_stats().constructLeafObjectTests++;
         rval = moab()->get_coords( &*i, 1, coords[0].array() );
         if (MB_SUCCESS != rval)
           return rval;
@@ -872,7 +872,7 @@ namespace moab {
         // non-polyhedron elements
       std::vector<EntityHandle> dum_vector;
       for (i = elem_begin; i != poly_begin; ++i) {
-        tree_stats().leafObjectTests++;
+        tree_stats().constructLeafObjectTests++;
         rval = moab()->get_connectivity( *i, conn, count, true, &dum_vector);
         if (MB_SUCCESS != rval) 
           return rval;
@@ -916,7 +916,7 @@ namespace moab {
   
         // polyhedra
       for (i = poly_begin; i != set_begin; ++i) {
-        tree_stats().leafObjectTests++;
+        tree_stats().constructLeafObjectTests++;
         rval = moab()->get_connectivity( *i, conn, count, true );
         if (MB_SUCCESS != rval) 
           return rval;
@@ -950,7 +950,7 @@ namespace moab {
         // sets
       BoundBox tbox;
       for (i = set_begin; i != elems.end(); ++i) {
-        tree_stats().leafObjectTests++;
+        tree_stats().constructLeafObjectTests++;
         rval = tbox.update(*moab(), *i);
         if (MB_SUCCESS != rval)
           return rval;
@@ -1354,7 +1354,7 @@ namespace moab {
       treeStats.leavesVisited++;
       if (myEval && params) {
         rval = myEval->find_containing_entity(node, point, iter_tol, inside_tol,
-                                              leaf_out, params->array(), &treeStats.leafObjectTests);
+                                              leaf_out, params->array(), &treeStats.traversalLeafObjectTests);
         if (MB_SUCCESS != rval) return rval;
       }
       else 
@@ -1494,7 +1494,7 @@ namespace moab {
             EntityHandle ent;
             CartVect params;
             rval = myEval->find_containing_entity(node.handle, from_point, iter_tol, inside_tol,
-                                                  ent, params.array(), &treeStats.leafObjectTests);
+                                                  ent, params.array(), &treeStats.traversalLeafObjectTests);
             if (MB_SUCCESS != rval) return rval;
             else if (ent) {
               result_list.push_back(ent);

diff --git a/src/BVHTree.cpp b/src/BVHTree.cpp
index e2592fb..2c13871 100644
--- a/src/BVHTree.cpp
+++ b/src/BVHTree.cpp
@@ -151,6 +151,7 @@ namespace moab
         const BoundBox &box = i->myBox;
         for (unsigned int dim = 0; dim < 3; ++dim){
           const unsigned int index = Bucket::bucket_index(splitsPerDir, box, interval, dim);
+          assert(index < buckets[dim].size());
           Bucket &bucket = buckets[dim][index];
           if (bucket.mySize > 0)
             bucket.boundingBox.update(box);
@@ -452,7 +453,7 @@ namespace moab
         if (MB_SUCCESS != rval) return rval;
         
         for(Range::iterator i = entities.begin(); i != entities.end(); i++) {
-          treeStats.leafObjectTests++;
+          treeStats.traversalLeafObjectTests++;
           myEval->set_ent_handle(*i);
           myEval->reverse_eval(&point[0], iter_tol, inside_tol, params.array(), &is_inside);
           if (is_inside) {
@@ -518,7 +519,7 @@ namespace moab
           EntityHandle entity = 0;
           treeStats.leavesVisited++;
           ErrorCode rval = myEval->find_containing_entity(startSetHandle+i, point, iter_tol, inside_tol,
-                                                          entity, params.array(), &treeStats.leafObjectTests);
+                                                          entity, params.array(), &treeStats.traversalLeafObjectTests);
           if (entity) return entity;
           else if (MB_SUCCESS != rval) return 0;
         }
@@ -584,7 +585,7 @@ namespace moab
         }
         else if (myTree[ind].dim == 3 && myEval && params) {
           rval = myEval->find_containing_entity(startSetHandle+ind, point, iter_tol, inside_tol,
-                                                leaf_out, params->array(), &treeStats.leafObjectTests);
+                                                leaf_out, params->array(), &treeStats.traversalLeafObjectTests);
           if (leaf_out || MB_SUCCESS != rval) return rval;
         }
         else {
@@ -657,7 +658,7 @@ namespace moab
           EntityHandle ent;
           CartVect params;
           rval = myEval->find_containing_entity(startSetHandle+ind, from_point, iter_tol, inside_tol,
-                                                ent, params.array(), &treeStats.leafObjectTests);
+                                                ent, params.array(), &treeStats.traversalLeafObjectTests);
           if (MB_SUCCESS != rval) return rval;
           else if (ent) {
             result_list.push_back(ent);

diff --git a/src/LocalDiscretization/ElemEvaluator.cpp b/src/LocalDiscretization/ElemEvaluator.cpp
index 209cd11..68ef791 100644
--- a/src/LocalDiscretization/ElemEvaluator.cpp
+++ b/src/LocalDiscretization/ElemEvaluator.cpp
@@ -57,7 +57,7 @@ namespace moab {
         if (det < std::numeric_limits<double>::epsilon()) {
           *tmp_inside = (*inside_f)(params, ndim, inside_tol);
           if (!(*tmp_inside)) return MB_SUCCESS;
-          else return MB_FAILURE;
+          else return MB_INDEX_OUT_OF_RANGE;
         }
 
           // new params tries to eliminate residual

diff --git a/src/LocalDiscretization/LinearTet.cpp b/src/LocalDiscretization/LinearTet.cpp
index 6d590e7..d8d381e 100644
--- a/src/LocalDiscretization/LinearTet.cpp
+++ b/src/LocalDiscretization/LinearTet.cpp
@@ -126,10 +126,15 @@ namespace moab
 
       int iters=0;
         // while |res| larger than tol
+      int dum, *tmp_inside = (inside ? inside : &dum);
       while (res % res > error_tol_sqr) {
-        if(++iters>25)
-          return MB_FAILURE;
-
+        if(++iters>25) {
+            // if we haven't converged but we're outside, that's defined as success
+          *tmp_inside = (*inside_f)(params, ndim, inside_tol);
+          if (!(*tmp_inside)) return MB_SUCCESS;
+          else return MB_INDEX_OUT_OF_RANGE;
+        }
+        
           // new params tries to eliminate residual
         *cvparams -= Ji * res;
 

diff --git a/src/LocalDiscretization/moab/ElemEvaluator.hpp b/src/LocalDiscretization/moab/ElemEvaluator.hpp
index 6a1efd0..9989dfc 100644
--- a/src/LocalDiscretization/moab/ElemEvaluator.hpp
+++ b/src/LocalDiscretization/moab/ElemEvaluator.hpp
@@ -118,8 +118,8 @@ namespace moab {
   public:
         /** \brief Constructor 
          * \param impl MOAB instance
-         * \param ent Entity handle to cache on the evaluator
-         * \param tag Tag to cache on the evaluator
+         * \param ent Entity handle to cache on the evaluator; if non-zero, calls set_ent_handle, which does some other stuff.
+         * \param tag Tag to cache on the evaluator; if non-zero, calls set_tag_handle, which does some other stuff too.
          * \param tagged_ent_dim Dimension of entities to be tagged to cache on the evaluator
          */
       ElemEvaluator(Interface *impl, EntityHandle ent = 0, Tag tag = 0, int tagged_ent_dim = -1);

diff --git a/src/moab/BVHTree.hpp b/src/moab/BVHTree.hpp
index 354d3a1..eb0e4e4 100644
--- a/src/moab/BVHTree.hpp
+++ b/src/moab/BVHTree.hpp
@@ -260,6 +260,7 @@ namespace moab {
                            const int index, const BoundBox &box, 
                            const int depth=0);
 
+        // builds up vector of HandleData, which caches elements' bounding boxes
       ErrorCode construct_element_vec(std::vector<HandleData> &handle_data_vec,
                                       const Range &elements, 
                                       BoundBox & bounding_box);
@@ -300,7 +301,8 @@ namespace moab {
       std::cout << "index: " << std::ceil(center/length)-1 << std::endl;
 #endif
 #endif
-      return std::ceil(center/length)-1;
+      unsigned int cl = std::ceil(center/length);
+      return (cl > 0 ? cl-1 : 0);
     }
 
     inline BVHTree::BVHTree(Interface *impl) : 

diff --git a/src/moab/TreeStats.hpp b/src/moab/TreeStats.hpp
index 4ae685b..0bb9478 100644
--- a/src/moab/TreeStats.hpp
+++ b/src/moab/TreeStats.hpp
@@ -43,8 +43,11 @@ namespace moab
         //! print the contents of this structure
       void print() const ;
 
-        //! output the contents of this structure on a single line
-      void output() const ;
+        //! output all the contents of this structure on a single line
+      void output_all_stats(const bool with_endl = true) const ;
+
+        //! output just the traversal stats of this structure on a single line
+      void output_trav_stats(const bool with_endl = true) const ;
 
         // times
       double initTime;
@@ -53,13 +56,18 @@ namespace moab
       unsigned int maxDepth;
       unsigned int numNodes;
       unsigned int numLeaves;
+      double avgObjPerLeaf;
+      unsigned int minObjPerLeaf;
+      unsigned int maxObjPerLeaf;
+      
 
         // traversal statistics
-      unsigned int nodesVisited;
-      unsigned int leavesVisited;
-      unsigned int numTraversals;
-      unsigned int leafObjectTests;
-      unsigned int boxElemTests;
+      unsigned int nodesVisited; // number of tree nodes visited since last reset
+      unsigned int leavesVisited; // number of tree leaves visited since last reset
+      unsigned int numTraversals; // number of tree traversals since last reset
+      unsigned int constructLeafObjectTests; // during construction, number of tests of objects (e.g. elements)
+      unsigned int traversalLeafObjectTests; // during traversals, number of tests of objects (e.g. elements)
+      unsigned int boxElemTests; // during construction, number of calls to GeomUtil::box_elem_overlap (KD tree only)
 
   private:
       ErrorCode traverse(Interface *impl, EntityHandle node, unsigned int &depth);
@@ -71,7 +79,13 @@ namespace moab
       maxDepth = 0;
       numNodes = 0;
       numLeaves = 0;
-      return traverse(impl, root_node, maxDepth);
+      avgObjPerLeaf = 0.0;
+      minObjPerLeaf = 0;
+      maxObjPerLeaf = 0;
+      
+      ErrorCode rval = traverse(impl, root_node, maxDepth);
+      avgObjPerLeaf = (avgObjPerLeaf > 0 ? avgObjPerLeaf/(double)numLeaves : 0.0);
+      return rval;
     }
       
     inline ErrorCode TreeStats::traverse(Interface *impl, EntityHandle node, unsigned int &depth) 
@@ -84,6 +98,11 @@ namespace moab
       if (MB_SUCCESS != rval) return rval;
       if (children.empty()) {
         numLeaves++;
+        rval = impl->get_entities_by_handle(node, children);
+        if (MB_SUCCESS != rval) return rval;
+        avgObjPerLeaf += children.size();
+        minObjPerLeaf = std::min((unsigned int)children.size(), minObjPerLeaf);
+        maxObjPerLeaf = std::max((unsigned int)children.size(), maxObjPerLeaf);
         return MB_SUCCESS;
       }
       else {
@@ -104,6 +123,11 @@ namespace moab
       maxDepth = 0;
       numNodes = 0;
       numLeaves = 0;
+      constructLeafObjectTests = 0;
+      boxElemTests = 0;
+      avgObjPerLeaf = 0.0;
+      minObjPerLeaf = 0.0;
+      maxObjPerLeaf = 0.0;
       
       reset_trav_stats();
     }
@@ -113,8 +137,7 @@ namespace moab
       nodesVisited = 0;
       leavesVisited = 0;
       numTraversals = 0;
-      leafObjectTests = 0;
-      boxElemTests = 0;
+      traversalLeafObjectTests = 0;
     }
     
     inline void TreeStats::print() const {
@@ -124,17 +147,32 @@ namespace moab
       std::cout << "Num leaves        = " << numLeaves << std::endl;
       std::cout << "Max depth         = " << maxDepth << std::endl << std::endl;
 
+      std::cout << "Avg objs per leaf = " << avgObjPerLeaf << std::endl;
+      std::cout << "Min objs per leaf = " << minObjPerLeaf << std::endl;
+      std::cout << "Max objs per leaf = " << maxObjPerLeaf << std::endl;
+
+      std::cout << "Construction Leaf Object Tests = " << constructLeafObjectTests << std::endl;
+      std::cout << "Box-Element Tests = " << boxElemTests << 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;
-      std::cout << "Box-Element Tests = " << boxElemTests << std::endl;
+      std::cout << "Traversal Leaf Object Tests = " << traversalLeafObjectTests << std::endl;
+    }
+
+    inline void TreeStats::output_all_stats(const bool with_endl) const 
+    {
+      std::cout << initTime << " " << numNodes << " " << numLeaves << " " << maxDepth << " " 
+                << avgObjPerLeaf << " " << minObjPerLeaf << " " << maxObjPerLeaf << " "
+                << constructLeafObjectTests << " " << boxElemTests << " "
+                << nodesVisited << " " << leavesVisited << " " << numTraversals << " " << traversalLeafObjectTests << " ";
+      if (with_endl) std::cout << std::endl;
     }
 
-    inline void TreeStats::output() const 
+    inline void TreeStats::output_trav_stats(const bool with_endl) const 
     {
-      std::cout << initTime << " " << nodesVisited << " " << leavesVisited << " " << numTraversals << " " << leafObjectTests << " " << boxElemTests
-                << " # initTime, nodesVisited, leavesVisited, numTraversals, leafObjectTests, boxElemTests" << std::endl;
+      std::cout << nodesVisited << " " << leavesVisited << " " << numTraversals << " " << traversalLeafObjectTests << " ";
+      if (with_endl) std::cout << std::endl;
     }
 }
 


https://bitbucket.org/fathomteam/moab/commits/c88d8437a1c2/
Changeset:   c88d8437a1c2
Branch:      master
User:        tautges
Date:        2014-03-17 18:41:58
Summary:     Adding a timing class for spatial locator; all times on this object are local, but a function is provided for
accumulating results across procs.

Affected #:  4 files

diff --git a/src/Makefile.am b/src/Makefile.am
index 5772d12..a9adf0d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -193,6 +193,7 @@ nobase_libMOAB_la_include_HEADERS = \
   moab/SetIterator.hpp \
   moab/Skinner.hpp \
   moab/SpatialLocator.hpp \
+  moab/SpatialLocatorTimes.hpp \
   moab/SpectralMeshTool.hpp \
   moab/Tree.hpp \
   moab/TreeStats.hpp \

diff --git a/src/SpatialLocator.cpp b/src/SpatialLocator.cpp
index 702399e..8556a81 100644
--- a/src/SpatialLocator.cpp
+++ b/src/SpatialLocator.cpp
@@ -11,13 +11,14 @@
 #include "moab/ParallelComm.hpp"
 #endif
 
-bool debug = true;
+bool debug = false;
 
 namespace moab 
 {
 
     SpatialLocator::SpatialLocator(Interface *impl, Range &elems, Tree *tree, ElemEvaluator *eval) 
-            : mbImpl(impl), myElems(elems), myDim(-1), myTree(tree), elemEval(eval), iCreatedTree(false)
+            : mbImpl(impl), myElems(elems), myDim(-1), myTree(tree), elemEval(eval), iCreatedTree(false),
+              timerInitialized(false)
     {
       create_tree();
       
@@ -178,14 +179,20 @@ namespace moab
       TupleList TLforward_o; //TLforward_outbound
       TupleList TLsearch_results_o; //TLsearch_results_outbound
 
+        // initialize timer 
+      myTimer.time_elapsed();
+      timerInitialized = true;
       
         // steps 1-2 - initialize the alternative decomposition box from global box
       rval = initialize_intermediate_partition(pc);
+      if (rval != MB_SUCCESS) return rval;
       
         //steps 3-6 - set up TLreg_o, gs_transfer, gather registrations
       rval = register_src_with_intermediate_procs(pc, abs_iter_tol, TLreg_o);
       if (rval != MB_SUCCESS) return rval;
 
+      myTimes.slTimes[SpatialLocatorTimes::INTMED_INIT] = myTimer.time_elapsed();
+
         // actual parallel point location using intermediate partition
 
         // target_pts: TL(to_proc, tgt_index, x, y, z): tuples sent to source mesh procs representing pts to be located
@@ -219,6 +226,8 @@ namespace moab
       if (pc)
         pc->proc_config().crystal_router()->gs_transfer(1, TLquery_o, 0);
 
+      myTimes.slTimes[SpatialLocatorTimes::INTMED_SEND] = myTimer.time_elapsed();
+
         //now read forwarding requests and forward to corresponding procs
         //TLquery_o is now TLforw_req_i
 
@@ -244,9 +253,17 @@ namespace moab
 
       }
 
+      myTimes.slTimes[SpatialLocatorTimes::INTMED_SEARCH] = myTimer.time_elapsed();
+
       if (pc)
         pc->proc_config().crystal_router()->gs_transfer(1, TLforward_o, 0);
 
+      myTimes.slTimes[SpatialLocatorTimes::SRC_SEND] = myTimer.time_elapsed();
+
+        // cache time here, because locate_points also calls elapsed functions and we want to account
+        // for tuple list initialization here
+      double tstart = myTimer.time_since_birth();
+      
         //step 12
         //now read Point Search requests
         //TLforward_o is now TLsearch_req_i
@@ -285,10 +302,14 @@ namespace moab
       }
       locTable.disableWriteAccess();
 
+      myTimes.slTimes[SpatialLocatorTimes::SRC_SEARCH] =  myTimer.time_since_birth() - tstart;
+      myTimer.time_elapsed(); // call this to reset last time called
+
         //step 14: send TLsearch_results_o and receive TLloc_i
       if (pc)
         pc->proc_config().crystal_router()->gs_transfer(1, TLsearch_results_o, 0);
 
+      myTimes.slTimes[SpatialLocatorTimes::TARG_RETURN] = myTimer.time_elapsed();
 
         // store proc/index tuples in parLocTable
       parLocTable.initialize(2, 0, 0, 0, num_points);
@@ -308,6 +329,8 @@ namespace moab
                   << " (" << 100.0*((double)num_found/num_points) << "%)" << std::endl;
       }
       
+      myTimes.slTimes[SpatialLocatorTimes::TARG_STORE] = myTimer.time_elapsed();
+
       return MB_SUCCESS;
     }
 
@@ -317,6 +340,13 @@ namespace moab
                                             const double rel_iter_tol, const double abs_iter_tol, 
                                             const double inside_tol) 
     {
+      bool i_initialized = false;
+      if (!timerInitialized) {
+        myTimer.time_elapsed();
+        timerInitialized = true;
+        i_initialized = true;
+      }
+      
       assert(!verts.empty() && mbImpl->type_from_handle(*verts.rbegin()) == MBVERTEX);
       std::vector<double> pos(3*verts.size());
       ErrorCode rval = mbImpl->get_coords(verts, &pos[0]);
@@ -324,6 +354,10 @@ namespace moab
       rval = locate_points(&pos[0], verts.size(), rel_iter_tol, abs_iter_tol, inside_tol);
       if (MB_SUCCESS != rval) return rval;
       
+        // only call this if I'm the top-level function, since it resets the last time called
+      if (i_initialized) 
+        myTimes.slTimes[SpatialLocatorTimes::SRC_SEARCH] =  myTimer.time_elapsed();
+
       return MB_SUCCESS;
     }
     
@@ -331,6 +365,12 @@ namespace moab
                                             const double rel_iter_tol, const double abs_iter_tol, 
                                             const double inside_tol) 
     {
+      bool i_initialized = false;
+      if (!timerInitialized) {
+        myTimer.time_elapsed();
+        timerInitialized = true;
+        i_initialized = true;
+      }
         // initialize to tuple structure (p_ui, hs_ul, r[3]_d) (see header comments for locTable)
       locTable.initialize(1, 0, 1, 3, num_points);
       locTable.enableWriteAccess();
@@ -341,7 +381,12 @@ namespace moab
       std::fill(locTable.vi_wr, locTable.vi_wr+num_points, 0);
       locTable.set_n(num_points);
       if (MB_SUCCESS != rval) return rval;
+
       
+        // only call this if I'm the top-level function, since it resets the last time called
+      if (i_initialized) 
+        myTimes.slTimes[SpatialLocatorTimes::SRC_SEARCH] =  myTimer.time_elapsed();
+
       return MB_SUCCESS;
     }
       
@@ -350,11 +395,24 @@ namespace moab
                                             const double rel_iter_tol, const double abs_iter_tol, 
                                             const double inside_tol)
     {
+      bool i_initialized = false;
+      if (!timerInitialized) {
+        myTimer.time_elapsed();
+        timerInitialized = true;
+        i_initialized = true;
+      }
+
       assert(!verts.empty() && mbImpl->type_from_handle(*verts.rbegin()) == MBVERTEX);
       std::vector<double> pos(3*verts.size());
       ErrorCode rval = mbImpl->get_coords(verts, &pos[0]);
       if (MB_SUCCESS != rval) return rval;
-      return locate_points(&pos[0], verts.size(), ents, params, is_inside, rel_iter_tol, abs_iter_tol, inside_tol);
+      rval = locate_points(&pos[0], verts.size(), ents, params, is_inside, rel_iter_tol, abs_iter_tol, inside_tol);
+
+        // only call this if I'm the top-level function, since it resets the last time called
+      if (i_initialized) 
+        myTimes.slTimes[SpatialLocatorTimes::SRC_SEARCH] =  myTimer.time_elapsed();
+
+      return rval;
     }
 
     ErrorCode SpatialLocator::locate_points(const double *pos, int num_points,
@@ -362,6 +420,13 @@ namespace moab
                                             const double rel_iter_tol, const double abs_iter_tol, 
                                             const double inside_tol)
     {
+      bool i_initialized = false;
+      if (!timerInitialized) {
+        myTimer.time_elapsed();
+        timerInitialized = true;
+        i_initialized = true;
+      }
+
       double tmp_abs_iter_tol = abs_iter_tol;
       if (rel_iter_tol && !tmp_abs_iter_tol) {
           // relative epsilon given, translate to absolute epsilon using box dimensions
@@ -389,6 +454,10 @@ namespace moab
         if (is_inside) is_inside[i] = (ents[i] ? true : false);
       }
       
+        // only call this if I'm the top-level function, since it resets the last time called
+      if (i_initialized) 
+        myTimes.slTimes[SpatialLocatorTimes::SRC_SEARCH] =  myTimer.time_elapsed();
+
       return rval;
     }
     

diff --git a/src/moab/SpatialLocator.hpp b/src/moab/SpatialLocator.hpp
index 2690058..95e6feb 100644
--- a/src/moab/SpatialLocator.hpp
+++ b/src/moab/SpatialLocator.hpp
@@ -35,6 +35,8 @@
 #include "moab/Range.hpp"
 #include "moab/TupleList.hpp"
 #include "moab/BoundBox.hpp"
+#include "moab/SpatialLocatorTimes.hpp"
+#include "moab/CpuTimer.hpp"
 
 #include <string>
 #include <vector>
@@ -166,7 +168,13 @@ namespace moab {
       
         /* set elemEval */
       void elem_eval(ElemEvaluator *eval) {elemEval = eval; if (myTree) myTree->set_eval(eval);}
+
+        /** \brief Get spatial locator times object */
+      SpatialLocatorTimes &sl_times() {return myTimes;}
       
+        /** \brief Get spatial locator times object */
+      const SpatialLocatorTimes &sl_times() const {return myTimes;}
+        
   private:
 
 #ifdef USE_MPI
@@ -262,6 +270,17 @@ namespace moab {
          */
       std::map<int, BoundBox> srcProcBoxes;
 
+        /* \brief Timing object for spatial location
+         */
+      SpatialLocatorTimes myTimes;
+
+        /* \brief Timer object to manage overloaded search functions
+         */
+      CpuTimer myTimer;
+      
+        /* \brief Flag to manage initialization of timer for overloaded search functions
+         */
+      bool timerInitialized;
     };
 
     inline SpatialLocator::~SpatialLocator() 

diff --git a/src/moab/SpatialLocatorTimes.hpp b/src/moab/SpatialLocatorTimes.hpp
new file mode 100644
index 0000000..e0b210d
--- /dev/null
+++ b/src/moab/SpatialLocatorTimes.hpp
@@ -0,0 +1,138 @@
+/**\file SpatialLocatorTimes.hpp
+ * \class moab::SpatialLocatorTimes
+ * \brief Statistics for spatial location
+ *
+ * Class to accumulate statistics on performance of spatial location.  This structure stores
+ * only local (single proc) statistics, but provides functions for accumulating max/min/avg
+ * time properties for performance reporting.
+ *
+ * Similar to TreeStats, this class is very lightweight, with most variables publicly accessible.
+ * 
+ */
+
+#ifndef SPATIALLOCATORTIMES_HPP
+#define SPATIALLOCATORTIMES_HPP
+
+#include "moab/Interface.hpp"
+
+#include <iostream>
+
+#ifdef USE_MPI
+#include "moab_mpi.h"
+#endif
+
+namespace moab 
+{
+class SpatialLocatorTimes
+{
+public:
+    /* constructor
+     */
+  SpatialLocatorTimes() {reset();}
+  
+    /* \brief Reset all stats defined here
+     */
+  void reset();
+  
+    /* \brief Output header for stats names
+     */
+  void output_header(bool print_endl = false) const;
+
+    /* \brief Output stats all on one line
+     */
+  void output(bool print_head = false, bool print_endl = false) const;
+
+#ifdef USE_MPI
+    /* \brief Accumulate times over all processors into provided array
+     * Max and min is accumulated over all processors, onto root, for each stat.  If avg_stats is non-NULL,
+     * all stats are gathered to root so average can be taken too.
+     *
+     * This function must be called collectively on the communicator
+     * \param comm MPI communictor over which this accumulation is done
+     * \param max_times Array of size NUM_STATS into which max times are inserted
+     * \param min_times Array of size NUM_STATS into which min times are inserted
+     * \param avg_times Array of size NUM_STATS into which avg times are inserted; if NULL, no avg times are computed.
+
+     */
+  ErrorCode accumulate_times(MPI_Comm comm, double *max_times, double *min_times, 
+                             double *avg_times = NULL);
+#endif
+
+    /* \brief Enumeration to identify fields in performance data
+     */
+  enum {INTMED_INIT = 0,       // time to compute intermediate partition, incl global bounding box         
+        INTMED_SEND,           // time to send search points from target to intermediate parts             
+        INTMED_SEARCH,         // time to find candidate src boxes for search points on intermidiate procs 
+        SRC_SEND,              // time to send search points to src procs                                  
+        SRC_SEARCH,            // time to search local box/elements on src procs                           
+        TARG_RETURN,           // time to return point location data to target procs
+        TARG_STORE,            // time to store point location into local SpatialLocator object
+        NUM_STATS              // number of stats, useful for array sizing and terminating loops over stats
+  };
+  
+  double slTimes[NUM_STATS];
+};
+
+inline void SpatialLocatorTimes::reset() 
+{
+  for (int i = 0; i < NUM_STATS; i++) slTimes[i] = 0.0;
+}
+
+#ifdef USE_MPI
+inline ErrorCode SpatialLocatorTimes::accumulate_times(MPI_Comm comm, 
+                                                       double *min_times, double *max_times, double *avg_times) 
+{
+  ErrorCode rval = MB_SUCCESS;
+  int success = MPI_Reduce(slTimes, min_times, NUM_STATS, MPI_DOUBLE, MPI_MIN, 0, comm);
+  if (!success) rval = MB_FAILURE;
+  
+  success = MPI_Reduce(slTimes, max_times, NUM_STATS, MPI_DOUBLE, MPI_MAX, 0, comm);
+  if (!success) rval = MB_FAILURE;
+  
+  if (avg_times) {
+    int sz, rank;
+    MPI_Comm_size(comm, &sz);
+    MPI_Comm_rank(comm, &rank);
+    std::vector<double> all_times;
+    if (!rank) all_times.resize(NUM_STATS*sz+NUM_STATS);
+    success = MPI_Gather(slTimes, NUM_STATS, MPI_DOUBLE, (rank ? NULL : &all_times[0]), NUM_STATS, MPI_DOUBLE, 0, comm);
+    if (!success) rval = MB_FAILURE;
+    if (!rank) {
+      std::fill(avg_times, avg_times+NUM_STATS, 0.0);
+      for (int p = 0; p < sz; p++) {
+        for (int s = 0; s < NUM_STATS; s++)
+          avg_times[s] += all_times[p*NUM_STATS+s];
+      }
+    
+      for (int s = 0; s <= NUM_STATS; s++) avg_times[s] /= (double)sz;
+    }
+  }
+  
+  return rval;
+}
+#endif
+
+  /* \brief Output stats all on one line
+   */
+inline void SpatialLocatorTimes::output_header(bool print_endl) const 
+{
+  std::cout << "Intmed_init Intmed_send Intmed_search src_send src_search targ_return targ_store";
+  if (print_endl) std::cout << std::endl;
+}
+
+  /* \brief Output stats all on one line
+   */
+inline void SpatialLocatorTimes::output(bool print_head, bool print_endl) const 
+{
+  if (print_head) output_header(true);
+  for (int i = 0; i < NUM_STATS; i++) std::cout << slTimes[i] << " ";
+  
+  if (print_endl) std::cout << std::endl;
+}
+    
+
+} // namespace moab
+
+#endif
+    
+

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