source: branches/source_numpy_conversion/anuga/fit_interpolate/search_functions.py @ 6768

Last change on this file since 6768 was 5905, checked in by rwilson, 16 years ago

NumPy? conversion.

File size: 8.0 KB
Line 
1"""
2General functions used in fit and interpolate.
3
4   Ole Nielsen, Stephen Roberts, Duncan Gray
5   Geoscience Australia, 2006.
6
7"""
8import time
9
10import numpy
11
12from anuga.utilities.numerical_tools import get_machine_precision
13from anuga.config import max_float
14
15initial_search_value = 'uncomment search_functions code first'#0
16search_one_cell_time = initial_search_value
17search_more_cells_time = initial_search_value
18
19#FIXME test what happens if a
20LAST_TRIANGLE = [[-10,[(numpy.array([max_float,max_float]),
21                        numpy.array([max_float,max_float]),
22                        numpy.array([max_float,max_float])),
23                       (numpy.array([1,1]),numpy.array([0,0]),numpy.array([-1.1,-1.1]))]]]
24
25def search_tree_of_vertices(root, mesh, x):
26    """
27    Find the triangle (element) that the point x is in.
28
29    Inputs:
30        root: A quad tree of the vertices
31        mesh: The underlying mesh
32        x:    The point being placed
33   
34    Return:
35        element_found, sigma0, sigma1, sigma2, k
36
37        where
38        element_found: True if a triangle containing x was found
39        sigma0, sigma1, sigma2: The interpolated values
40        k: Index of triangle (if found)
41
42    """
43    global search_one_cell_time
44    global search_more_cells_time
45
46    #Find triangle containing x:
47    element_found = False
48
49    # This will be returned if element_found = False
50    sigma2 = -10.0
51    sigma0 = -10.0
52    sigma1 = -10.0
53    k = -10.0
54
55    # Search the last triangle first
56    try:
57        element_found, sigma0, sigma1, sigma2, k = \
58            _search_triangles_of_vertices(mesh, last_triangle, x)
59    except:
60        element_found = False
61                   
62    #print "last_triangle", last_triangle
63    if element_found is True:
64        #print "last_triangle", last_triangle
65        return element_found, sigma0, sigma1, sigma2, k
66
67    # This was only slightly faster than just checking the
68    # last triangle and it significantly slowed down
69    # non-gridded fitting
70    # If the last element was a dud, search its neighbours
71    #print "last_triangle[0][0]", last_triangle[0][0]
72    #neighbours = mesh.get_triangle_neighbours(last_triangle[0][0])
73    #print "neighbours", neighbours
74    #neighbours = []
75  #   for k in neighbours:
76#         if k >= 0:
77#             tri = mesh.get_vertex_coordinates(k,
78#                                                    absolute=True)
79#             n0 = mesh.get_normal(k, 0)
80#             n1 = mesh.get_normal(k, 1)
81#             n2 = mesh.get_normal(k, 2)
82#             triangle =[[k,(tri, (n0, n1, n2))]]
83#             element_found, sigma0, sigma1, sigma2, k = \
84#                            _search_triangles_of_vertices(mesh,
85#                                                          triangle, x)
86#             if element_found is True:
87#                 return element_found, sigma0, sigma1, sigma2, k
88           
89    #t0 = time.time()
90    # Get triangles in the cell that the point is in.
91    # Triangle is a list, first element triangle_id,
92    # second element the triangle
93    triangles = root.search(x[0], x[1])
94    is_more_elements = True
95   
96    element_found, sigma0, sigma1, sigma2, k = \
97                   _search_triangles_of_vertices(mesh,
98                                                 triangles, x)
99    #search_one_cell_time += time.time()-t0
100    #print "search_one_cell_time",search_one_cell_time
101    #t0 = time.time()
102    while not element_found and is_more_elements:
103        triangles, branch = root.expand_search()
104        if branch == []:
105            # Searching all the verts from the root cell that haven't
106            # been searched.  This is the last try
107            element_found, sigma0, sigma1, sigma2, k = \
108                           _search_triangles_of_vertices(mesh, triangles, x)
109            is_more_elements = False
110        else:
111            element_found, sigma0, sigma1, sigma2, k = \
112                       _search_triangles_of_vertices(mesh, triangles, x)
113        #search_more_cells_time += time.time()-t0
114    #print "search_more_cells_time", search_more_cells_time
115       
116    return element_found, sigma0, sigma1, sigma2, k
117
118
119def _search_triangles_of_vertices(mesh, triangles, x):
120    """Search for triangle containing x amongs candidate_vertices in mesh
121
122    This is called by search_tree_of_vertices once the appropriate node
123    has been found from the quad tree.
124   
125
126    This function is responsible for most of the compute time in
127    fit and interpolate.
128    """
129    global last_triangle
130   
131    # these statments are needed if triangles is empty
132    #Find triangle containing x:
133    element_found = False
134
135    # This will be returned if element_found = False
136    sigma2 = -10.0
137    sigma0 = -10.0
138    sigma1 = -10.0
139    k = -10
140   
141    #For all vertices in same cell as point x
142    for k, tri_verts_norms in triangles:
143        tri = tri_verts_norms[0]
144        n0, n1, n2 = tri_verts_norms[1]
145        # k is the triangle index
146        # tri is a list of verts (x, y), representing a tringle
147        # Find triangle that contains x (if any) and interpolate
148        element_found, sigma0, sigma1, sigma2 =\
149                       find_triangle_compute_interpolation(tri, n0, n1, n2, x)
150        if element_found is True:
151            # Don't look for any other triangles in the triangle list
152            last_triangle = [[k,tri_verts_norms]]
153            break
154    return element_found, sigma0, sigma1, sigma2, k
155
156
157           
158def find_triangle_compute_interpolation(triangle, n0, n1, n2, x):
159    """Compute linear interpolation of point x and triangle k in mesh.
160    It is assumed that x belongs to triangle k.max_float
161    """
162
163    # Get the three vertex_points of candidate triangle k
164    xi0, xi1, xi2 = triangle
165
166    # this is where we can call some fast c code.
167     
168    # Integrity check - machine precision is too hard
169    # so we use hardwired single precision
170    epsilon = 1.0e-6
171   
172    if  x[0] > max(xi0[0], xi1[0], xi2[0]) + epsilon:
173        # print "max(xi0[0], xi1[0], xi2[0])", max(xi0[0], xi1[0], xi2[0])
174        return False,0,0,0
175    if  x[0] < min(xi0[0], xi1[0], xi2[0]) - epsilon:
176        return False,0,0,0
177    if  x[1] > max(xi0[1], xi1[1], xi2[1]) + epsilon:
178        return False,0,0,0
179    if  x[1] < min(xi0[1], xi1[1], xi2[1]) - epsilon:
180        return False,0,0,0
181   
182    # machine precision on some machines (e.g. nautilus)
183    epsilon = get_machine_precision() * 2
184   
185    # Compute interpolation - return as soon as possible
186    #  print "(xi0-xi1)", (xi0-xi1)
187    # print "n0", n0
188    # print "dot((xi0-xi1), n0)", dot((xi0-xi1), n0)
189   
190    sigma0 = numpy.dot((x-xi1), n0)/numpy.dot((xi0-xi1), n0)
191    if sigma0 < -epsilon:
192        return False,0,0,0
193    sigma1 = numpy.dot((x-xi2), n1)/numpy.dot((xi1-xi2), n1)
194    if sigma1 < -epsilon:
195        return False,0,0,0
196    sigma2 = numpy.dot((x-xi0), n2)/numpy.dot((xi2-xi0), n2)
197    if sigma2 < -epsilon:
198        return False,0,0,0
199   
200    # epsilon = 1.0e-6
201    # we want to speed this up, so don't do assertions
202    #delta = abs(sigma0+sigma1+sigma2-1.0) # Should be close to zero
203    #msg = 'abs(sigma0+sigma1+sigma2-1) = %.15e, eps = %.15e'\
204    #      %(delta, epsilon)
205    #assert delta < epsilon, msg
206
207
208    # Check that this triangle contains the data point
209    # Sigmas are allowed to get negative within
210    # machine precision on some machines (e.g. nautilus)
211    #if sigma0 >= -epsilon and sigma1 >= -epsilon and sigma2 >= -epsilon:
212    #    element_found = True
213    #else:
214    #    element_found = False
215    return True, sigma0, sigma1, sigma2
216
217def set_last_triangle():
218    global last_triangle
219    last_triangle = LAST_TRIANGLE
220   
221def search_times():
222
223    global search_one_cell_time
224    global search_more_cells_time
225
226    return search_one_cell_time, search_more_cells_time
227
228def reset_search_times():
229
230    global search_one_cell_time
231    global search_more_cells_time
232    search_one_cell_time = initial_search_value
233    search_more_cells_time = initial_search_value
Note: See TracBrowser for help on using the repository browser.