Changeset 7713


Ignore:
Timestamp:
May 11, 2010, 10:59:06 AM (15 years ago)
Author:
James Hudson
Message:

Optimisations to tree traversal added for a 30% speed boost.

Location:
anuga_core/source/anuga
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • anuga_core/source/anuga/fit_interpolate/general_fit_interpolate.py

    r7711 r7713  
    3636import numpy as num
    3737
    38 
    39 # tests fail if 2 is used
    40 MAX_VERTICES_PER_CELL = 13 # A value of 8 or lower can cause problems,
    41                            # if a vert has 9 triangles.
    4238                           
    4339build_quadtree_time = 0
  • anuga_core/source/anuga/fit_interpolate/search_functions.py

    r7711 r7713  
    3333# FIXME(Ole): Could we come up with a less confusing structure?
    3434# FIXME(James): remove this global var
    35 LAST_TRIANGLE = [[-10,
     35LAST_TRIANGLE = [[-10, -10,
    3636                   (num.array([[max_float, max_float],
    3737                               [max_float, max_float],
     
    6464    global search_more_cells_time
    6565
    66     # Search the last triangle first
     66    if last_triangle[0][1] != -10:
     67        # check the last triangle found first
     68        element_found, sigma0, sigma1, sigma2, k = \
     69                   _search_triangles_of_vertices(last_triangle, x)
     70
     71        if element_found:
     72            return True, sigma0, sigma1, sigma2, k
     73
     74    # search to bottom of tree from last found leaf
     75    branch = last_triangle[0][1]
     76   
     77    if branch == -10:
     78        branch = root   
     79   
     80    tri_data = branch.search(x[0], x[1])
     81    triangles = _trilist_from_data(mesh, tri_data)           
    6782    element_found, sigma0, sigma1, sigma2, k = \
    68         _search_triangles_of_vertices(last_triangle, x)
    69                    
    70     if element_found is True:
    71         return element_found, sigma0, sigma1, sigma2, k
    72 
    73    
    74     # Get triangles in the cell that the point is in.
    75     tri_indices = root.search(x[0], x[1])
    76     triangles = _trilist_from_indices(mesh, tri_indices)
    77    
    78     element_found, sigma0, sigma1, sigma2, k = \
    79                    _search_triangles_of_vertices(triangles, x)
    80 
    81     is_more_elements = True
    82    
    83     # while not element_found and is_more_elements:
    84         # triangles, branch = root.expand_search()
    85         # if branch == []:
    86             # # Searching all the verts from the root cell that haven't
    87             # # been searched.  This is the last try
    88             # element_found, sigma0, sigma1, sigma2, k = \
    89                            # _search_triangles_of_vertices(triangles, x)
    90             # is_more_elements = False
    91         # else:
    92             # element_found, sigma0, sigma1, sigma2, k = \
    93                        # _search_triangles_of_vertices(triangles, x)
    94                        
    95        
     83                _search_triangles_of_vertices(triangles, x)
     84    if element_found:
     85        return True, sigma0, sigma1, sigma2, k
     86
     87    # search rest of tree
     88    element_found = False
     89    while branch:
     90        if not branch.parent:
     91            # search from top of tree if we are at root
     92            siblings = [root]
     93        else:
     94            siblings = branch.get_siblings()
     95           
     96        for sibling in siblings:
     97            tri_data = sibling.search(x[0], x[1])
     98            triangles = _trilist_from_data(mesh, tri_data)           
     99            element_found, sigma0, sigma1, sigma2, k = \
     100                        _search_triangles_of_vertices(triangles, x)
     101            if element_found:
     102                return True, sigma0, sigma1, sigma2, k
     103                                   
     104        branch = branch.parent
     105        if branch:
     106            tri_data = branch.test_leaves(x[0], x[1])
     107            triangles = _trilist_from_data(mesh, tri_data)           
     108            element_found, sigma0, sigma1, sigma2, k = \
     109                        _search_triangles_of_vertices(triangles, x)
     110            if element_found:
     111                return True, sigma0, sigma1, sigma2, k       
     112
    96113    return element_found, sigma0, sigma1, sigma2, k
     114
     115
     116    ## Get triangles in the cell that the point is in.
     117    #tri_data = root.search(x[0], x[1])
     118    #triangles = _trilist_from_data(mesh, tri_data)
     119   
     120    #element_found, sigma0, sigma1, sigma2, k = \
     121                   #_search_triangles_of_vertices(triangles, x)
     122
     123    #if element_found:
     124        #return True, sigma0, sigma1, sigma2, k
    97125
    98126
     
    116144    sigma1 = -10.0
    117145    k = -10
     146   
    118147    # For all vertices in same cell as point x
    119148    element_found = False   
    120     for k, tri_verts_norms in triangles:
     149    for k, node, tri_verts_norms in triangles:
    121150        tri = tri_verts_norms[0]
    122151        tri = ensure_numeric(tri)       
     
    135164
    136165            # Don't look for any other triangles in the triangle list
    137             last_triangle = [[k, tri_verts_norms]]
     166            last_triangle = [[k, node, tri_verts_norms]]
    138167            break           
    139168           
     
    141170
    142171
    143 def _trilist_from_indices(mesh, indices):
     172def _trilist_from_data(mesh, indices):
    144173    """return a list of lists. For the inner lists,
    145174    The first element is the triangle index,
     
    151180
    152181    ret_list = []
    153     for i in indices:
     182    for i, node in indices:
    154183        vertices = mesh.get_vertex_coordinates(triangle_id=i, absolute=True)
    155184        n0 = mesh.get_normal(i, 0)
    156185        n1 = mesh.get_normal(i, 1)
    157186        n2 = mesh.get_normal(i, 2)
    158         ret_list.append([i, [vertices, (n0, n1, n2)]])
     187        ret_list.append([i, node, [vertices, (n0, n1, n2)]])
    159188    return ret_list
    160189               
     
    196225class MeshQuadtree(Cell):
    197226    """ A quadtree constructed from the given mesh.
     227        This class is actually the root node of a tree,
     228        and derives from a Cell.
    198229    """
    199230    def __init__(self, mesh):
     
    205236        extents = AABB(*mesh.get_extent(absolute=True))   
    206237        extents.grow(1.001) # To avoid round off error
    207         Cell.__init__(self, extents)
     238        Cell.__init__(self, extents, None)  # root has no parent
    208239       
    209240        N = len(mesh)
  • anuga_core/source/anuga/fit_interpolate/test_meshquad.py

    r7711 r7713  
    4343
    4444        # test a point that falls within a triangle
    45         result = Q.search(10, 10, get_vertices=True)
     45        result = Q.search(10, 10)
    4646        assert type(result) in [types.ListType,types.TupleType],\
    4747                            'should be a list'
    48         pos, index = result[0]
     48        index, parent = result[0]
    4949        self.assertEqual(index, 1)
    5050
     
    138138        results = Q.search(4.5, 3)
    139139        assert len(results) == 1
    140         self.assertEqual(results[0], 2)
     140        idx, _ = results[0]
     141        self.assertEqual(idx, 2)
    141142        results = Q.search(5,4.)
    142143        self.assertEqual(len(results),1)
    143         self.assertEqual(results[0], 2)
     144        idx, _ = results[0]
     145        self.assertEqual(idx, 2)
    144146       
    145147    def NOtest_get_parent():
  • anuga_core/source/anuga/fit_interpolate/test_search_functions.py

    r7711 r7713  
    55from search_functions import search_tree_of_vertices, set_last_triangle
    66from search_functions import _search_triangles_of_vertices
    7 from search_functions import _trilist_from_indices
     7from search_functions import _trilist_from_data
    88from search_functions import compute_interpolation_values, MeshQuadtree
    99
     
    156156        x = ensure_numeric([0.5, 0.5])
    157157
    158         triangles = _trilist_from_indices(mesh, root.search(x[0], x[1]))
     158        triangles = _trilist_from_data(mesh, root.search(x[0], x[1]))
    159159   
    160160        found, sigma0, sigma1, sigma2, k = \
     
    175175                  [10, 3]]:
    176176               
    177             triangles = _trilist_from_indices(mesh, root.search(x[0], x[1]))
     177            triangles = _trilist_from_data(mesh, root.search(x[0], x[1]))
    178178
    179179            #print x, candidate_vertices
  • anuga_core/source/anuga/geometry/quad.py

    r7712 r7713  
    1919    """
    2020 
    21     def __init__(self, extents,
     21    def __init__(self, extents, parent, depth = 0,
    2222         name = 'cell'):
    2323 
     
    2626   
    2727        self.extents = extents
     28        self.parent = parent
     29        self.searched = [-10, -15]
     30        self.depth = depth
    2831       
    2932        # The points in this cell     
     
    3336   
    3437    def __repr__(self):
    35         str = '%s: leaves: %d' \
    36                % (self.name , len(self.leaves))   
     38        str = '(%d)%s: leaves: %d' \
     39               % (self.depth, self.name , len(self.leaves))   
    3740        if self.children:
    3841            str += ', children: %d' % (len(self.children))
     
    8285            subregion1, subregion2 = self.extents.split()
    8386            if subregion1.is_trivial_in(new_region):
    84                 self.children = [Cell(subregion1), Cell(subregion2)]   
     87                self.children = [Cell(subregion1, self, depth=self.depth+1), Cell(subregion2, self, depth=self.depth+1)]   
    8588                self.children[0]._insert(new_leaf)
    8689                return
    8790            elif subregion2.is_trivial_in(new_region):
    88                 self.children = [Cell(subregion1), Cell(subregion2)]   
     91                self.children = [Cell(subregion1, self, depth=self.depth+1), Cell(subregion2, self, depth=self.depth+1)]   
    8992                self.children[1]._insert(new_leaf)
    9093                return               
     
    132135 
    133136
    134     def search(self, x, y, get_vertices = False):
     137    def search(self, x, y):
    135138        """return a list of possible intersections with geometry"""
     139
     140 #       if self.searched == [x,y]:
     141 #           print 'ERROR: already searched at ', [x,y]
     142 #       self.searched = [x,y]
    136143       
     144        intersecting_regions = self.test_leaves(x, y)
     145       
     146        # recurse down into nodes that the point passes through
     147        if self.children:
     148            for child in self.children:   
     149                if child.extents.contains(x, y):
     150                    intersecting_regions.extend(child.search(x, y))
     151             
     152        return intersecting_regions
     153 
     154 
     155    def test_leaves(self, x, y):
    137156        intersecting_regions = []
    138157       
     
    141160            aabb, data = leaf
    142161            if aabb.contains(x, y):
    143                 if get_vertices:
    144                     intersecting_regions.append(leaf)
    145                 else:
    146                     intersecting_regions.append(data)
    147        
    148         # recurse down into nodes that the point passes through
    149         if self.children:
    150             for child in self.children:   
    151                 if child.extents.contains(x, y):
    152                     intersecting_regions.extend(child.search(x, y, get_vertices))
    153              
    154         return intersecting_regions
    155        
     162                intersecting_regions.append((data, self))
     163               
     164        return intersecting_regions               
     165 
     166 
     167    def get_siblings(self):
     168        """ return parent and siblings of this node.
     169        """
     170        if not self.parent:
     171            return []
     172         
     173        siblings = list(self.parent.children)
     174        siblings.remove(self)
     175        return siblings
     176               
  • anuga_core/source/anuga/geometry/test_geometry.py

    r7711 r7713  
    5959       
    6060    def test_add_data(self):
    61         cell = Cell(AABB(0,10, 0,5))
     61        cell = Cell(AABB(0,10, 0,5), None)
    6262        cell.insert([(AABB(1,3, 1, 3), 111), (AABB(8,9, 1, 2), 222),  \
    6363                     (AABB(7, 8, 3, 4), 333), (AABB(1, 10, 0, 1), 444)])
     
    7070       
    7171    def test_search(self):
    72         test_region = (AABB(8,9, 1, 2), 222)
    73         cell = Cell(AABB(0,10, 0,5))
    74         cell.insert([(AABB(1,3, 1, 3), 111), test_region,  \
     72        test_tag = 222
     73        cell = Cell(AABB(0,10, 0,5), None)
     74        cell.insert([(AABB(1,3, 1, 3), 111), (AABB(8,9, 1, 2), test_tag),  \
    7575                     (AABB(7, 8, 3, 4), 333), (AABB(1, 10, 0, 1), 444)])
    7676
    77         result =  cell.search(x = 8.5, y = 1.5, get_vertices=True)
     77        result = cell.search(x = 8.5, y = 1.5)
    7878        assert type(result) in [types.ListType,types.TupleType],\
    7979                            'should be a list'
    80         self.assertEqual(result, [test_region], 'only 1 point should intersect')
     80        assert(len(result) == 1)
     81        data, node = result[0]
     82        self.assertEqual(data, test_tag, 'only 1 point should intersect')
    8183
     84    def test_get_siblings(self):
     85        """ Make sure children know their parent. """
     86        cell = Cell(AABB(0,10, 0,5), None)
     87        cell.insert([(AABB(1,3, 1, 3), 111), (AABB(8,9, 1, 2), 222)])
     88        assert len(cell.children) == 2
     89        assert cell.parent == None
     90        assert cell.children[0].parent == cell
     91        assert cell.children[1].parent == cell
    8292
    8393    def test_clear_1(self):
    84         cell = Cell(AABB(0,10, 0,5))   
     94        cell = Cell(AABB(0,10, 0,5), None)   
    8595        cell.insert([(AABB(1,3, 1, 3), 111), (AABB(8,9, 1, 2), 222),  \
    8696                     (AABB(7, 8, 3, 4), 333), (AABB(1, 10, 0, 1), 444)])
     
    94104
    95105if __name__ == "__main__":
    96     mysuite = unittest.makeSuite(Test_Quad,'test')
     106    mysuite = unittest.makeSuite(Test_Geometry, 'test')
    97107    runner = unittest.TextTestRunner()
    98108    runner.run(mysuite)
Note: See TracChangeset for help on using the changeset viewer.