Changeset 316
- Timestamp:
- Sep 16, 2004, 5:31:08 PM (21 years ago)
- Location:
- inundation/ga/storm_surge/pyvolution
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
inundation/ga/storm_surge/pyvolution/least_squares.py
r309 r316 7 7 8 8 9 from mesh import Mesh 10 9 """Classes implementing general 2D geometrical mesh of triangles. 10 11 Ole Nielsen, Stephen Roberts, Duncan Gray, Christopher Zoppou 12 Geoscience Australia, 2004 13 """ 14 15 16 class Mesh: 17 """Collection of triangular elements (purely geometric) 18 19 A triangular element is defined in terms of three vertex ids, 20 ordered counter clock-wise, 21 each corresponding to a given coordinate set. 22 Vertices from different elements can point to the same 23 coordinate set. 24 25 Coordinate sets are implemented as an N x 2 Numeric array containing 26 x and y coordinates. 27 28 29 To instantiate: 30 Mesh(coordinates, triangles) 31 32 where 33 34 coordinates is either a list of 2-tuples or an Mx2 Numeric array of 35 floats representing all x, y coordinates in the mesh. 36 37 triangles is either a list of 3-tuples or an Nx3 Numeric array of 38 integers representing indices of all vertices in the mesh. 39 Each vertex is identified by its index i in [0, M-1]. 40 41 42 Example: 43 a = [0.0, 0.0] 44 b = [0.0, 2.0] 45 c = [2.0,0.0] 46 e = [2.0, 2.0] 47 48 points = [a, b, c, e] 49 triangles = [ [1,0,2], [1,2,3] ] #bac, bce 50 mesh = Mesh(points, triangles) 51 52 #creates two triangles: bac and bce 53 54 This is a cut down version of mesh from pyvolution\mesh.py 55 """ 56 57 def __init__(self, coordinates, triangles): 58 """ 59 Build triangles from x,y coordinates (sequence of 2-tuples or 60 Mx2 Numeric array of floats) and triangles (sequence of 3-tuples 61 or Nx3 Numeric array of non-negative integers). 62 """ 63 64 from Numeric import array, zeros, Int, Float, maximum, sqrt, sum 65 66 self.triangles = array(triangles).astype(Int) 67 self.coordinates = array(coordinates) 68 69 #Input checks 70 msg = 'Triangles must an Nx2 Numeric array or a sequence of 2-tuples' 71 assert len(self.triangles.shape) == 2, msg 72 73 msg = 'Coordinates must an Mx2 Numeric array or a sequence of 2-tuples' 74 assert len(self.coordinates.shape) == 2, msg 75 76 msg = 'Vertex indices reference non-existing coordinate sets' 77 assert max(max(self.triangles)) <= self.coordinates.shape[0], msg 78 79 80 #Register number of elements (N) 81 self.number_of_elements = N = self.triangles.shape[0] 82 83 84 self.normals = zeros((N, 6), Float) 85 86 #Get x,y coordinates for all triangles and store 87 self.vertex_coordinates = V = self.compute_vertex_coordinates() 88 89 #Initialise each triangle 90 for i in range(N): 91 #if i % (N/10) == 0: print '(%d/%d)' %(i, N) 92 93 x0 = V[i, 0]; y0 = V[i, 1] 94 x1 = V[i, 2]; y1 = V[i, 3] 95 x2 = V[i, 4]; y2 = V[i, 5] 96 97 #Area 98 area = abs((x1*y0-x0*y1)+(x2*y1-x1*y2)+(x0*y2-x2*y0))/2 99 100 msg = 'Triangle (%f,%f), (%f,%f), (%f, %f)' %(x0,y0,x1,y1,x2,y2) 101 msg += ' is degenerate: area == %f' %area 102 assert area > 0.0, msg 103 104 105 #Normals 106 #The normal vectors 107 # - point outward from each edge 108 # - are orthogonal to the edge 109 # - have unit length 110 # - Are enumerated according to the opposite corner: 111 # (First normal is associated with the edge opposite 112 # the first vertex, etc) 113 # - Stored as six floats n0x,n0y,n1x,n1y,n2x,n2y per triangle 114 115 n0 = array([x2 - x1, y2 - y1]) 116 l0 = sqrt(sum(n0**2)) 117 118 n1 = array([x0 - x2, y0 - y2]) 119 l1 = sqrt(sum(n1**2)) 120 121 n2 = array([x1 - x0, y1 - y0]) 122 l2 = sqrt(sum(n2**2)) 123 124 #Normalise 125 n0 /= l0 126 n1 /= l1 127 n2 /= l2 128 129 #Compute and store 130 self.normals[i, :] = [n0[1], -n0[0], 131 n1[1], -n1[0], 132 n2[1], -n2[0]] 133 134 135 #Build vertex list 136 self.build_vertexlist() 137 138 139 140 def __len__(self): 141 return self.number_of_elements 142 143 def __repr__(self): 144 return 'Mesh: %d triangles, %d elements'\ 145 %(self.coordinates.shape[0], len(self)) 146 147 148 149 #DSG I don't know if I need this 150 def build_vertexlist(self): 151 pass 152 153 # maybe add this latter.. 154 def check_integrity(self): 155 pass 156 157 158 def get_normals(self): 159 """Return all normal vectors. 160 Return normal vectors for all triangles as an Nx6 array 161 (ordered as x0, y0, x1, y1, x2, y2 for each triangle) 162 """ 163 return self.normals 164 165 166 def get_normal(self, i, j): 167 """Return normal vector j of the i'th triangle. 168 Return value is the numeric array slice [x, y] 169 """ 170 return self.normals[i, 2*j:2*j+2] 171 172 173 174 def get_vertex_coordinates(self): 175 """Return all vertex coordinates. 176 Return all vertex coordinates for all triangles as an Nx6 array 177 (ordered as x0, y0, x1, y1, x2, y2 for each triangle) 178 """ 179 return self.vertex_coordinates 180 181 182 def get_vertex_coordinate(self, i, j): 183 """Return coordinates for vertex j of the i'th triangle. 184 Return value is the numeric array slice [x, y] 185 """ 186 return self.vertex_coordinates[i, 2*j:2*j+2] 187 188 189 def compute_vertex_coordinates(self): 190 """Return vertex coordinates for all triangles as an Nx6 array 191 (ordered as x0, y0, x1, y1, x2, y2 for each triangle) 192 """ 193 194 #FIXME: Perhaps they should be ordered as in obj files?? 195 #See quantity.get_vertex_values 196 197 from Numeric import zeros, Float 198 199 N = self.number_of_elements 200 vertex_coordinates = zeros((N, 6), Float) 201 202 for i in range(N): 203 for j in range(3): 204 k = self.triangles[i,j] #Index of vertex 0 205 v_k = self.coordinates[k] 206 vertex_coordinates[i, 2*j+0] = v_k[0] 207 vertex_coordinates[i, 2*j+1] = v_k[1] 208 209 return vertex_coordinates 210 211 def get_triangles(self, unique=False): 212 """Get connectivity 213 If unique is True give them only once as stored internally. 214 If unique is False return 215 """ 216 217 if unique is True: 218 return self.triangles 219 else: 220 from Numeric import reshape, array, Int 221 222 m = len(self) #Number of volumes 223 M = 3*m #Total number of unique vertices 224 return reshape(array(range(M)).astype(Int), (m,3)) 225 226 227 228 from Numeric import zeros, array, Float, Int, dot,transpose 229 from LinearAlgebra import solve_linear_equations 230 231 EPSILON = 1.0e-13 11 232 12 233 class Interpolation(Mesh): 13 234 14 def __init__(self, vertex_coordinates, triangles, data_coordinates):235 def __init__(self, vertex_coordinates, triangles, point_coordinates): 15 236 """ Build interpolation matrix mapping from 16 237 function values at vertices to function values at data points … … 24 245 integers representing indices of all vertices in the mesh. 25 246 26 data_coordinates: List of coordinate pairs [x, y] of data points247 point_coordinates: List of coordinate pairs [x, y] of data points 27 248 (or an nx2 Numeric array) 28 249 29 250 """ 30 251 31 from Numeric import zeros, array, Float, Int, dot32 from config import epsilon33 34 252 #Convert input to Numeric arrays 35 data_coordinates = array(data_coordinates).astype(Float)253 point_coordinates = array(point_coordinates).astype(Float) 36 254 vertex_coordinates = array(vertex_coordinates).astype(Float) 37 255 triangles = array(triangles).astype(Int) … … 43 261 #Build n x m interpolation matrix 44 262 m = vertex_coordinates.shape[0] #Number of basis functions (1/vertex) 45 n = data_coordinates.shape[0] #Number of data points263 n = point_coordinates.shape[0] #Number of data points 46 264 47 265 self.A_m = zeros((n,m), Float) … … 51 269 #For each data_coordinate point 52 270 53 x = data_coordinates[i]271 x = point_coordinates[i] 54 272 for k in range(len(self)): 55 273 #For each triangle (brute force) … … 72 290 73 291 #FIXME: Maybe move out to test or something 74 assert abs(sigma0 + sigma1 + sigma2 - 1.0) < epsilon292 assert abs(sigma0 + sigma1 + sigma2 - 1.0) < EPSILON 75 293 76 294 … … 89 307 90 308 def smooth_to_mesh(self, z): 91 from Numeric import zeros, array, Float,transpose,dot 92 from LinearAlgebra import solve_linear_equations 309 """ Linearly interpolate point data values to the vertices. 310 311 Inputs: 312 z: Vector of data at the point_coordinates. One value per point. 313 314 """ 93 315 #Convert input to Numeric arrays 94 316 z = array(z).astype(Float) … … 100 322 f = solve_linear_equations(self.AtA_m,Atz_m) 101 323 return f 324 325 def smooth_to_points(self, f): 326 """ Linearly interpolate point data values to the vertices. 327 328 Inputs: 329 z: Vector of data at the point_coordinates. One value per point. 330 331 """ 332 return dot(self.A_m,f) -
inundation/ga/storm_surge/pyvolution/test_least_squares.py
r309 r316 159 159 assert allclose(f, answer) 160 160 161 def test_smooth_to_meshII(self): 162 a = [0.0, 0.0] 163 b = [0.0, 5.0] 164 c = [5.0, 0.0] 165 points = [a, b, c] 166 triangles = [ [1,0,2] ] #bac 167 168 d1 = [1.0, 1.0] 169 d2 = [1.0, 2.0] 170 d3 = [3.0,1.0] 171 data_coords = [ d1, d2, d3] 172 z = self.linear_function(data_coords) 173 mesh = Interpolation(points, triangles, data_coords) 174 f = mesh.smooth_to_mesh(z) 175 answer = self.linear_function(points) 176 assert allclose(f, answer) 177 178 def test_smooth_to_meshIII(self): 179 a = [-1.0, 0.0] 180 b = [3.0, 4.0] 181 c = [4.0,1.0] 182 d = [-3.0, 2.0] #3 183 e = [-1.0,-2.0] 184 f = [1.0, -2.0] #5 185 186 vertices = [a, b, c, d,e,f] 187 triangles = [[0,1,3],[1,0,2],[0,4,5], [0,5,2]] #abd bac aef afc 188 189 190 point_coords = [[-2.0, 2.0], 191 [-1.0, 1.0], 192 [0.0,2.0], 193 [1.0, 1.0], 194 [2.0, 1.0], 195 [0.0,0.0], 196 [1.0, 0.0], 197 [0.0, -1.0], 198 [-0.2,-0.5], 199 [-0.9, -1.5], 200 [0.5, -1.9], 201 [3.0,1.0]] 202 203 z = self.linear_function(point_coords) 204 mesh = Interpolation(vertices, triangles, point_coords) 205 f = mesh.smooth_to_mesh(z) 206 answer = self.linear_function(vertices) 207 assert allclose(f, answer) 208 209 def linear_function(self,point): 210 point = array(point) 211 return point[:,0]+point[:,1] 212 213 def test_smooth_to_points(self): 214 v0 = [0.0, 0.0] 215 v1 = [0.0, 5.0] 216 v2 = [5.0, 0.0] 217 218 vertices = [v0, v1, v2] 219 triangles = [ [1,0,2] ] #bac 220 221 222 d0 = [1.0, 1.0] 223 d1 = [1.0, 2.0] 224 d2 = [3.0,1.0] 225 point_coords = [ d0, d1, d2] 226 227 mesh = Interpolation(vertices, triangles, point_coords) 228 f = self.linear_function(vertices) 229 z = mesh.smooth_to_points(f) 230 answer = self.linear_function(point_coords) 231 #print "z",z 232 #print "answer",answer 233 assert allclose(z, answer) 234 235 def test_smooth_to_pointsII(self): 236 a = [-1.0, 0.0] 237 b = [3.0, 4.0] 238 c = [4.0,1.0] 239 d = [-3.0, 2.0] #3 240 e = [-1.0,-2.0] 241 f = [1.0, -2.0] #5 242 243 vertices = [a, b, c, d,e,f] 244 triangles = [[0,1,3],[1,0,2],[0,4,5], [0,5,2]] #abd bac aef afc 245 246 247 point_coords = [[-2.0, 2.0], 248 [-1.0, 1.0], 249 [0.0,2.0], 250 [1.0, 1.0], 251 [2.0, 1.0], 252 [0.0,0.0], 253 [1.0, 0.0], 254 [0.0, -1.0], 255 [-0.2,-0.5], 256 [-0.9, -1.5], 257 [0.5, -1.9], 258 [3.0,1.0]] 259 260 mesh = Interpolation(vertices, triangles, point_coords) 261 f = self.linear_function(vertices) 262 z = mesh.smooth_to_points(f) 263 answer = self.linear_function(point_coords) 264 #print "z",z 265 #print "answer",answer 266 assert allclose(z, answer) 161 267 #------------------------------------------------------------- 162 268 if __name__ == "__main__":
Note: See TracChangeset
for help on using the changeset viewer.