Changeset 2709
- Timestamp:
- Apr 12, 2006, 2:28:05 PM (19 years ago)
- Location:
- inundation
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
inundation/pyvolution/domain.py
r2648 r2709 1 1 """Class Domain - 2D triangular domains for finite-volume computations of 2 the shallow water wave equation2 conservation laws. 3 3 4 4 -
inundation/pyvolution/mesh.py
r2683 r2709 6 6 7 7 from general_mesh import General_mesh 8 from math import pi, sqrt 9 8 10 9 11 class Mesh(General_mesh): … … 125 127 #of inscribed circle is computed 126 128 127 from math import sqrt128 129 a = sqrt((x0-x1)**2+(y0-y1)**2) 129 130 b = sqrt((x1-x2)**2+(y1-y2)**2) … … 165 166 def set_to_inscribed_circle(self,safety_factor = 1): 166 167 #FIXME phase out eventually 167 from math import sqrt168 168 N = self.number_of_elements 169 169 V = self.vertex_coordinates … … 414 414 415 415 416 def get_boundary_polygon(self): 417 """Return bounding polygon as a list of points 418 419 FIXME: If triangles are listed as discontinuous 420 (e.g vertex coordinates listed multiple times), 421 this may not work as expected. 422 """ 416 def get_boundary_polygon(self, verbose = False): 417 """Return bounding polygon for mesh (counter clockwise) 418 419 Using the mesh boundary, derive a bounding polygon for this mesh. 420 If multiple vertex values are present, the algorithm will select the 421 path that contains the mesh. 422 """ 423 423 424 from Numeric import allclose, sqrt, array, minimum, maximum 424 425 426 427 #V = self.get_vertex_coordinates() 425 from utilities.numerical_tools import angle, ensure_numeric 426 427 428 # Get mesh extent 429 xmin, xmax, ymin, ymax = self.get_extent() 430 pmin = ensure_numeric([xmin, ymin]) 431 pmax = ensure_numeric([xmax, ymax]) 432 433 434 # Assemble dictionary of boundary segments and choose starting point 428 435 segments = {} 429 430 #pmin = (min(self.coordinates[:,0]), min(self.coordinates[:,1])) 431 #pmax = (max(self.coordinates[:,0]), max(self.coordinates[:,1])) 432 433 #FIXME:Can this be written more compactly, e.g. 434 #using minimum and maximium? 435 pmin = array( [min(self.coordinates[:,0]), 436 min(self.coordinates[:,1]) ] ) 437 438 pmax = array( [max(self.coordinates[:,0]), 439 max(self.coordinates[:,1]) ] ) 440 441 mindist = sqrt(sum( (pmax-pmin)**2 )) 436 inverse_segments = {} 437 mindist = sqrt(sum((pmax-pmin)**2)) #Start value across entire mesh 442 438 for i, edge_id in self.boundary.keys(): 443 # Find vertex ids for boundary segment439 # Find vertex ids for boundary segment 444 440 if edge_id == 0: a = 1; b = 2 445 441 if edge_id == 1: a = 2; b = 0 446 442 if edge_id == 2: a = 0; b = 1 447 443 448 A = tuple(self.get_vertex_coordinate(i, a))449 B = tuple(self.get_vertex_coordinate(i, b))450 451 # Take the point closest to pmin as starting point452 # Note: Could be arbitrary, but nice to have453 # a unique way of selecting454 dist_A = sqrt(sum( (A-pmin)**2))455 dist_B = sqrt(sum( (B-pmin)**2))456 457 #Find minimalpoint444 A = self.get_vertex_coordinate(i, a) # Start 445 B = self.get_vertex_coordinate(i, b) # End 446 447 # Take the point closest to pmin as starting point 448 # Note: Could be arbitrary, but nice to have 449 # a unique way of selecting 450 dist_A = sqrt(sum((A-pmin)**2)) 451 dist_B = sqrt(sum((B-pmin)**2)) 452 453 #Find lower leftmost point 458 454 if dist_A < mindist: 459 455 mindist = dist_A … … 464 460 465 461 462 # Sanity check 466 463 if p0 is None: 467 raise 'Weird' 468 p0 = A #We need a starting point (FIXME) 469 470 print 'A', A 471 print 'B', B 472 print 'pmin', pmin 473 print 474 475 segments[A] = B 464 raise Exception('Impossible') 465 466 467 # Register potential paths from A to B 468 if not segments.has_key(tuple(A)): 469 segments[tuple(A)] = [] # Empty list for candidate points 470 471 segments[tuple(A)].append(B) 472 473 476 474 477 475 478 476 #Start with smallest point and follow boundary (counter clock wise) 479 polygon = [p0] 480 while len(polygon) < len(self.boundary): 481 p1 = segments[p0] 477 polygon = [p0] # Storage for final boundary polygon 478 point_registry = {} # Keep track of storage to avoid multiple runs around boundary 479 # This will only be the case if there are more than one candidate 480 # FIXME (Ole): Perhaps we can do away with polygon and use 481 # only point_registry to save space. 482 483 point_registry[tuple(p0)] = 0 484 485 #while len(polygon) < len(self.boundary): 486 while len(point_registry) < len(self.boundary): 487 488 candidate_list = segments[tuple(p0)] 489 if len(candidate_list) > 1: 490 # Multiple points detected 491 # Take the candidate that is furthest to the clockwise direction, 492 # as that will follow the boundary. 493 494 495 if verbose: 496 print 'Point %s has multiple candidates: %s' %(str(p0), candidate_list) 497 498 499 # Choose vector against which all angles will be measured 500 if len(polygon) > 1: 501 v_prev = p0 - polygon[-2] # Vector that leads to p0 502 else: 503 # FIXME (Ole): What do we do if the first point has multiple candidates? 504 # Being the lower left corner, perhaps we can use the 505 # vector [1, 0], but I really don't know if this is completely 506 # watertight. 507 # Another option might be v_prev = [1.0, 0.0] 508 v_prev = [1.0, 0.0] 509 510 511 512 # Choose candidate with minimum angle 513 minimum_angle = 2*pi 514 for pc in candidate_list: 515 vc = pc-p0 # Candidate vector 516 517 # Angle between each candidate and the previous vector in [-pi, pi] 518 ac = angle(vc, v_prev) 519 if ac > pi: ac = pi-ac 520 521 # take the minimal angle corresponding to the rightmost vector 522 if ac < minimum_angle: 523 minimum_angle = ac 524 p1 = pc # Best candidate 525 526 527 if verbose is True: 528 print ' Best candidate %s, angle %f' %(p1, minimum_angle*180/pi) 529 530 else: 531 p1 = candidate_list[0] 532 533 if point_registry.has_key(tuple(p1)): 534 # We have completed the boundary polygon - yeehaa 535 break 536 else: 537 point_registry[tuple(p1)] = len(point_registry) 538 482 539 polygon.append(p1) 483 540 p0 = p1 541 484 542 485 543 return polygon … … 494 552 495 553 from config import epsilon 496 from math import pi497 554 from utilities.numerical_tools import anglediff 498 555 … … 537 594 538 595 #Normalise 539 from math import sqrt540 596 l_u = sqrt(u[0]*u[0] + u[1]*u[1]) 541 597 l_v = sqrt(v[0]*v[0] + v[1]*v[1]) -
inundation/pyvolution/test_mesh.py
r2532 r2709 849 849 850 850 851 def test_boundary_polygon_V(self): 852 """Create a discontinuous mesh (duplicate vertices) 853 and check that boundary is as expected 854 855 """ 856 from mesh import Mesh 857 from Numeric import zeros, Float 858 859 860 #Points 861 a = [0.0, 0.0] #0 862 b = [0.0, 0.5] #1 863 c = [0.0, 1.0] #2 864 d = [0.5, 0.0] #3 865 e = [0.5, 0.5] #4 866 f = [1.0, 0.0] #5 867 g = [1.0, 0.5] #6 868 h = [1.0, 1.0] #7 869 i = [1.5, 0.5] #8 870 871 #Duplicate points for triangles edg [4,3,6] (central) and 872 #gid [6,8,7] (top right boundary) to them disconnected 873 #from the others 874 875 e0 = [0.5, 0.5] #9 876 d0 = [0.5, 0.0] #10 877 g0 = [1.0, 0.5] #11 878 i0 = [1.5, 0.5] #12 879 880 881 points = [a, b, c, d, e, f, g, h, i, e0, d0, g0, i0] 882 883 884 885 #dea, bae, bec, fgd, 886 #edg, ghe, gfi, gih 887 #vertices = [ [3,4,0], [1,0,4], [1,4,2], [5,6,3], 888 # [4,3,6], [6,7,4], [6,5,8], [6,8,7]] 889 890 891 #dea, bae, bec, fgd, 892 #e0d0g0, ghe, gfi, g0i0h 893 vertices = [[3,4,0], [1,0,4], [1,4,2], [5,6,3], 894 [9,10,11], [6,7,4], [6,5,8], [11,12,7]] 895 896 mesh = Mesh(points, vertices) 897 898 mesh.check_integrity() 899 900 P = mesh.get_boundary_polygon() 901 902 #print P 903 904 assert len(P) == 8 905 assert allclose(P, [a, d, f, i, h, e, c, b]) 906 assert allclose(P, [(0.0, 0.0), (0.5, 0.0), (1.0, 0.0), (1.5, 0.5), (1.0, 1.0), (0.5, 0.5), (0.0, 1.0), (0.0, 0.5)]) 907 908 909 for p in points: 910 #print p, P 911 assert inside_polygon(p, P) 851 912 852 913 853 914 #------------------------------------------------------------- 854 915 if __name__ == "__main__": 855 suite = unittest.makeSuite(Test_Mesh,'test') 916 suite = unittest.makeSuite(Test_Mesh,'test_boundary_polygon') 917 #suite = unittest.makeSuite(Test_Mesh,'test') 856 918 runner = unittest.TextTestRunner() 857 919 runner.run(suite) -
inundation/pyvolution/test_shallow_water.py
r2620 r2709 3040 3040 3041 3041 3042 #Create a ntriangle shaped domain (reusing coordinates from domain 1),3042 #Create a triangle shaped domain (reusing coordinates from domain 1), 3043 3043 #formed from the lower and right hand boundaries and 3044 3044 #the sw-ne diagonal … … 3376 3376 if __name__ == "__main__": 3377 3377 suite = unittest.makeSuite(Test_Shallow_Water,'test') 3378 runner = unittest.TextTestRunner( )3378 runner = unittest.TextTestRunner(verbosity=1) 3379 3379 runner.run(suite) -
inundation/utilities/numerical_tools.py
r2704 r2709 57 57 58 58 def anglediff(v0, v1): 59 """Compute difference between angle of vector x0, y0 and x1, y1.59 """Compute difference between angle of vector v0 (x0, y0) and v1 (x1, y1). 60 60 This is used for determining the ordering of vertices, 61 61 e.g. for checking if they are counter clockwise. -
inundation/utilities/test_numerical_tools.py
r2704 r2709 47 47 48 48 assert allclose(angle([1.0, -1.0], [1.0, 1.0])/pi*180, 270.0) 49 assert allclose(angle([1.0, 0.0], [0.0, 1.0])/pi*180, 270.0) 49 assert allclose(angle([1.0, 0.0], [0.0, 1.0])/pi*180, 270.0) 50 51 #From test_get_boundary_polygon_V 52 v_prev = [-0.5, -0.5] 53 vc = [ 0.0, -0.5] 54 assert allclose(angle(vc, v_prev)/pi*180, 45.0) 55 56 vc = [ 0.5, 0.0] 57 assert allclose(angle(vc, v_prev)/pi*180, 135.0) 58 59 vc = [ -0.5, 0.5] 60 assert allclose(angle(vc, v_prev)/pi*180, 270.0) 61 62 50 63 51 64
Note: See TracChangeset
for help on using the changeset viewer.