source: anuga_core/source/anuga/fit_interpolate/search_functions.py @ 6152

Last change on this file since 6152 was 6152, checked in by rwilson, 15 years ago

Change Numeric imports to general form - ready to change to NumPy?.

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