[MOAB-dev] r1720 - MOAB/trunk

kraftche at mcs.anl.gov kraftche at mcs.anl.gov
Fri Mar 28 16:09:10 CDT 2008


Author: kraftche
Date: 2008-03-28 16:09:10 -0500 (Fri, 28 Mar 2008)
New Revision: 1720

Modified:
   MOAB/trunk/MBCore.cpp
   MOAB/trunk/MBCore.hpp
   MOAB/trunk/MBTest.cpp
Log:
Provide special case implementation for range-based get_adjacencies 
when (to_dimension == 0 && op == UNION).  Reduces kD-tree build time
by 85%.


Modified: MOAB/trunk/MBCore.cpp
===================================================================
--- MOAB/trunk/MBCore.cpp	2008-03-28 20:06:44 UTC (rev 1719)
+++ MOAB/trunk/MBCore.cpp	2008-03-28 21:09:10 UTC (rev 1720)
@@ -996,7 +996,72 @@
   return get_adjacencies(tmp_from_entities, to_dimension, create_if_missing, 
                          adj_entities, operation_type);
 }
+
+MBErrorCode MBCore::get_vertices( const MBRange& from_entities,
+                                  MBRange& adj_entities )
+{
+  const size_t DEFAULT_MAX_BLOCKS_SIZE = 4000;
+  const size_t MAX_OUTER_ITERATIONS = 100;
+
+  std::vector<MBEntityHandle> temp_vec, storage;
+  std::vector<MBEntityHandle>::const_iterator ti;
+  MBErrorCode result = MB_SUCCESS, tmp_result;
+  MBRange::const_iterator i = from_entities.begin();
+  MBRange::iterator ins;
+  const MBEntityHandle* conn;
+  int conn_len;
+
+    // Just copy any vertices from the input range into the output
+  size_t remaining = from_entities.size();
+  for (; i != from_entities.end() && TYPE_FROM_HANDLE(*i) == MBVERTEX; ++i) 
+    --remaining;
+  adj_entities.merge( from_entities.begin(), i );
   
+    // How many entities to work with at once? 2000 or so shouldn't require
+    // too much memory, but don't iterate in outer loop more than a
+    // 1000 times (make it bigger if many input entiites.) 
+  const size_t block_size = std::max( DEFAULT_MAX_BLOCKS_SIZE, remaining/MAX_OUTER_ITERATIONS );
+  while (remaining > 0) {
+    const size_t count = remaining > block_size ? block_size : remaining;
+    remaining -= count;
+    temp_vec.clear();
+    for (size_t j = 0; j < count; ++i, ++j) {
+      tmp_result = get_connectivity( *i, conn, conn_len, false, &storage );
+      if (MB_SUCCESS != tmp_result) {
+        result = tmp_result;
+        continue;
+      }
+
+      if (TYPE_FROM_HANDLE(*i) == MBPOLYHEDRON) {
+        storage.clear();
+        tmp_result = get_connectivity( conn, conn_len, storage );
+        if (MB_SUCCESS != tmp_result) {
+          result = tmp_result;
+          continue;
+        }
+        conn_len = storage.size();
+        conn = &storage[0];
+      }
+
+      const size_t oldsize = temp_vec.size();
+      temp_vec.resize( oldsize + conn_len );
+      memcpy( &temp_vec[oldsize], conn, sizeof(MBEntityHandle)*conn_len );
+    }
+
+    std::sort( temp_vec.begin(), temp_vec.end() );
+    ins = adj_entities.begin();
+    ti = temp_vec.begin();
+    while (ti != temp_vec.end()) {
+      MBEntityHandle first = *ti;
+      MBEntityHandle second = *ti;
+      for (++ti; ti != temp_vec.end() && (*ti - second <= 1); ++ti)
+        second = *ti;
+      ins = adj_entities.insert( ins, first, second );
+    }
+  }
+  return result;
+}
+
 MBErrorCode MBCore::get_adjacencies(const MBRange &from_entities,
                                       const int to_dimension,
                                       const bool create_if_missing,
@@ -1009,6 +1074,11 @@
   if(from_entities.size() == 0)
     return MB_SUCCESS;
 
+    // special case for getting all vertices
+  if (to_dimension == 0 && operation_type == MBInterface::UNION) {
+    return get_vertices( from_entities, adj_entities );
+  }
+
   MBRange temp_range;
   std::vector<MBEntityHandle> temp_vec;
   MBErrorCode result = MB_SUCCESS, tmp_result;

Modified: MOAB/trunk/MBCore.hpp
===================================================================
--- MOAB/trunk/MBCore.hpp	2008-03-28 20:06:44 UTC (rev 1719)
+++ MOAB/trunk/MBCore.hpp	2008-03-28 21:09:10 UTC (rev 1720)
@@ -276,6 +276,16 @@
                                          MBRange &adj_entities,
                                          const int operation_type = MBInterface::INTERSECT);
 
+      /**\brief Get all vertices for input entities
+       *
+       * Special case of get_adjacencies where to_dimension == 0
+       * and operation_type == MBInterface::UNION.  
+       *\Note This is not a variation of get_connectivity because
+       *      the behavior is different for polyhedra.
+       */
+    virtual MBErrorCode get_vertices( const MBRange& from_entities,
+                                      MBRange& vertices );
+
       //! Adds adjacencies
       /** \param from_handle entities 
           \param both_ways add the adjacency information to both the

Modified: MOAB/trunk/MBTest.cpp
===================================================================
--- MOAB/trunk/MBTest.cpp	2008-03-28 20:06:44 UTC (rev 1719)
+++ MOAB/trunk/MBTest.cpp	2008-03-28 21:09:10 UTC (rev 1720)
@@ -663,6 +663,69 @@
   return MB_SUCCESS;
 }
 
+MBErrorCode mb_adjacent_vertex_test( MBInterface* mb )
+{
+  MBErrorCode rval;
+  MBRange hexes, expt_vert, got_vert, some_hexes;
+  MBRange::const_iterator i, j;
+  int n;
+  
+    // get all hexes
+  rval = mb->get_entities_by_type( 0, MBHEX, hexes );
+  if (rval != MB_SUCCESS)
+    return rval;
+  if (hexes.empty())  // can't do test if no elements
+    return MB_FAILURE;
+  
+    // get every third hex and its vertices
+  n = 0;
+  for (i = hexes.begin(); i != hexes.end(); ++i) {
+    if (++n % 3)
+      continue;
+    some_hexes.insert( *i );
+    const MBEntityHandle* conn;
+    int len;
+    rval = mb->get_connectivity( *i, conn, len );
+    if (MB_SUCCESS != rval)
+      return rval;
+    for (int k = 0; k < len; ++k)
+      expt_vert.insert( conn[k] );
+  }
+  
+    // use get_adjacencies to get vertices
+  rval = mb->get_adjacencies( some_hexes, 0, false, got_vert, MBInterface::UNION );
+  if (MB_SUCCESS != rval) {
+    std::cout << "get_adjacencies failed with error code " << rval << std::endl;
+    return rval;
+  }
+  
+  i = expt_vert.begin();
+  j = got_vert.begin();
+  while (i != expt_vert.end() && j != got_vert.end()) {
+    if (*i < *j) {
+      std::cout << "Result missing vertex: " << *i << std::endl;
+      return MB_FAILURE;
+    }
+    else if (*j < *i) {
+      std::cout << "Result contains extra vertex: " << *j << std::endl;
+      return MB_FAILURE;
+    }
+    ++i;
+    ++j;
+  }
+  
+  if (i != expt_vert.end()) {
+    std::cout << "Result missing vertex: " << *i << std::endl;
+    return MB_FAILURE;
+  }
+  else if (j != got_vert.end()) {
+    std::cout << "Result contains extra vertex: " << *j << std::endl;
+    return MB_FAILURE;
+  }
+  
+  return MB_SUCCESS;
+}
+  
 MBErrorCode mb_adjacencies_test(MBInterface *mb) 
 {
     // this test does the following:
@@ -5780,6 +5843,7 @@
 
   cout << "\n\nMB TEST PROGRAM:\n\n";
 
+  RUN_TEST( mb_adjacent_vertex_test );
   RUN_TEST( mb_adjacencies_test );
   RUN_TEST( mb_vertex_coordinate_test );
   RUN_TEST( mb_vertex_tag_test );




More information about the moab-dev mailing list