def test_large(self): """test_larger mesh and different quad trees """ points, vertices, boundary = rectangular(10, 12, 1, 1) mesh = Mesh(points, vertices, boundary) #Test that points are arranged in a counter clock wise order mesh.check_integrity() root = MeshQuadtree(mesh) root.set_last_triangle() #print m, root.show() for x in [[0.6, 0.3], [0.1, 0.2], [0.7,0.7], [0.1,0.9], [0.4,0.6], [0.9,0.1], [10, 3]]: found, s0, s1, s2, k = root.search_fast(x) if k >= 0: V = mesh.get_vertex_coordinates(k) # nodes for triangle k assert is_inside_triangle(x, V, closed=True) assert is_inside_polygon(x, V) assert found is True else: assert found is False if k == 0: return
def get_triangle_containing_point(p, point, search_order=None): V = p.vols x = p.x y = p.y from anuga.geometry.polygon import is_outside_polygon, is_inside_polygon if search_order is None: # Estimate a good search order by finding the distance to the first # vertex of every triangle, and doing the search ordered by that # distance. point_distance2 = (x[V[:, 0]] - point[0])**2 + (y[V[:, 0]] - point[1])**2 point_distance_order = point_distance2.argsort().tolist() else: point_distance_order = search_order for i in point_distance_order: i0 = V[i, 0] i1 = V[i, 1] i2 = V[i, 2] poly = [[x[i0], y[i0]], [x[i1], y[i1]], [x[i2], y[i2]]] if is_inside_polygon(point, poly, closed=True): return i msg = 'Point %s not found within a triangle' % str(point) raise Exception(msg)
def compute_enquiry_index(self): # Get boundary (in absolute coordinates) bounding_polygon = self.domain_bounding_polygon #domain_centroids = self.domain.get_centroid_coordinates(absolute=True) #vertex_coordinates = self.domain.get_vertex_coordinates(absolute=True) point = self.enquiry_pt msg = 'Enquiry Point %s ' % str(point) msg += ' did not fall within the domain boundary.' assert is_inside_polygon(point, bounding_polygon), msg try: self.enquiry_index = self.domain.get_triangle_containing_point(self.enquiry_pt) except: msg = "Enquiry point %s doesn't intersect mesh, maybe inside a building, try reducing enquiry_gap" % str(self.enquiry_pt) raise Exception(msg) if self.enquiry_index in self.triangle_indices: msg = 'Enquiry point %s' % (self.enquiry_pt) msg += ' is in an inlet triangle' import warnings warnings.warn(msg)
def get_triangle_containing_point(self, point): """Return triangle id for triangle containing specified point (x,y) If point isn't within mesh, raise exception """ # FIXME(Ole): This function is currently brute force # because I needed it for diagnostics. # We should make it fast - probably based on the # quad tree structure. from anuga.geometry.polygon import is_outside_polygon,\ is_inside_polygon polygon = self.get_boundary_polygon() if is_outside_polygon(point, polygon): msg = 'Point %s is outside mesh' %str(point) raise Exception(msg) V = self.get_vertex_coordinates(absolute=True) # FIXME: Horrible brute force for i, triangle in enumerate(self.triangles): poly = V[3*i:3*i+3] if is_inside_polygon(point, poly, closed=True): return i msg = 'Point %s not found within a triangle' %str(point) raise Exception(msg)
def test_bigger(self): """test_bigger test larger mesh """ points, vertices, boundary = rectangular(4, 4, 1, 1) mesh = Mesh(points, vertices, boundary) #Test that points are arranged in a counter clock wise order mesh.check_integrity() root = MeshQuadtree(mesh) root.set_last_triangle() for x in [[0.6, 0.3], [0.1, 0.2], [0.7,0.7], [0.1,0.9], [0.4,0.6], [0.9,0.1], [10, 3]]: found, s0, s1, s2, k = root.search_fast(ensure_numeric(x)) if k >= 0: V = mesh.get_vertex_coordinates(k) # nodes for triangle k assert is_inside_polygon(x, V) assert found is True #print k, x else: assert found is False
def get_triangle_containing_point(p,point, search_order=None): V = p.vols x = p.x y = p.y from anuga.geometry.polygon import is_outside_polygon,is_inside_polygon if search_order is None: # Estimate a good search order by finding the distance to the first # vertex of every triangle, and doing the search ordered by that # distance. point_distance2 = (x[V[:,0]] - point[0])**2 + (y[V[:,0]]-point[1])**2 point_distance_order = point_distance2.argsort().tolist() else: point_distance_order = search_order for i in point_distance_order: i0 = V[i,0] i1 = V[i,1] i2 = V[i,2] poly = [ [x[i0], y[i0]], [x[i1], y[i1]], [x[i2], y[i2]] ] if is_inside_polygon(point, poly, closed=True): return i msg = 'Point %s not found within a triangle' %str(point) raise Exception(msg)
def test_underlying_function(self): """test_larger mesh and different quad trees """ return points, vertices, boundary = rectangular(2, 2, 1, 1) mesh = Mesh(points, vertices, boundary) root = MeshQuadtree(mesh) root.set_last_triangle() # One point x = ensure_numeric([0.5, 0.5]) found, sigma0, sigma1, sigma2, k = \ root._search_triangles_of_vertices(root.search(x), x) if k >= 0: V = mesh.get_vertex_coordinates(k) # nodes for triangle k assert is_inside_polygon(x, V) assert found is True else: assert found is False # More points for x in [[0.6, 0.3], [0.1, 0.2], [0.7,0.7], [0.1,0.9], [0.4,0.6], [0.9,0.1], [10, 3]]: triangles = root.search(x) #print x, candidate_vertices found, sigma0, sigma1, sigma2, k = \ root._search_triangles_of_vertices(triangles, ensure_numeric(x)) if k >= 0: V = mesh.get_vertex_coordinates(k) # nodes for triangle k assert is_inside_polygon(x, V) assert found is True else: assert found is False
def get_triangle_containing_point(p, point, search_order=None): """ Function to get the index of a triangle containing a point. It loops over all points in the mesh until it finds on that contains the point. The search order (i.e. order in which triangles defined by p.vols are searched) can be provided. If it is not, it is estimated by computing the distance from the point to the first vertex of every triangle, and searching from smallest to largest. @param p Object containing mesh vertex information (e.g. from plot_utils.get_output) @param point A single point @param search_order An optional integer array giving the order in which to search the mesh triangles @return The index such that the triangle defined by p.vols[index,:] contains the point """ V = p.vols x = p.x y = p.y from anuga.geometry.polygon import is_outside_polygon,is_inside_polygon if search_order is None: # Estimate a good search order by finding the distance to the first # vertex of every triangle, and doing the search ordered by that # distance. point_distance2 = (x[V[:,0]] - point[0])**2 + (y[V[:,0]]-point[1])**2 point_distance_order = point_distance2.argsort().tolist() else: point_distance_order = search_order for i in point_distance_order: i0 = V[i,0] i1 = V[i,1] i2 = V[i,2] poly = [ [x[i0], y[i0]], [x[i1], y[i1]], [x[i2], y[i2]] ] if is_inside_polygon(point, poly, closed=True): return i msg = 'Point %s not found within a triangle' %str(point) raise Exception(msg)
def __init__(self, domain, quantity_name, rate=0.0, center=None, radius=None, polygon=None, default_rate=None, verbose=False): from math import pi, cos, sin if domain.numproc > 1: msg = 'Not implemented to run in parallel' assert self.parallel_safe(), msg if center is None: msg = 'I got radius but no center.' assert radius is None, msg if radius is None: msg += 'I got center but no radius.' assert center is None, msg self.domain = domain self.quantity_name = quantity_name self.rate = rate self.center = ensure_numeric(center) self.radius = radius self.polygon = polygon self.verbose = verbose self.value = 0.0 # Can be used to remember value at # previous timestep in order to obtain rate # Get boundary (in absolute coordinates) bounding_polygon = domain.get_boundary_polygon() # Update area if applicable if center is not None and radius is not None: assert len(center) == 2 msg = 'Polygon cannot be specified when center and radius are' assert polygon is None, msg # Check that circle center lies within the mesh. msg = 'Center %s specified for forcing term did not' % str(center) msg += 'fall within the domain boundary.' assert is_inside_polygon(center, bounding_polygon), msg # Check that circle periphery lies within the mesh. N = 100 periphery_points = [] for i in range(N): theta = 2*pi*i/100 x = center[0] + radius*cos(theta) y = center[1] + radius*sin(theta) periphery_points.append([x,y]) for point in periphery_points: msg = 'Point %s on periphery for forcing term' % str(point) msg += ' did not fall within the domain boundary.' assert is_inside_polygon(point, bounding_polygon), msg if polygon is not None: # Check that polygon lies within the mesh. for point in self.polygon: msg = 'Point %s in polygon for forcing term' % str(point) msg += ' did not fall within the domain boundary.' assert is_inside_polygon(point, bounding_polygon), msg # Pointer to update vector self.update = domain.quantities[self.quantity_name].explicit_update # Determine indices in flow area N = len(domain) points = domain.get_centroid_coordinates(absolute=True) # Calculate indices in exchange area for this forcing term self.exchange_indices = None if self.center is not None and self.radius is not None: # Inlet is circular inlet_region = 'center=%s, radius=%s' % (self.center, self.radius) self.exchange_indices = [] for k in range(N): x, y = points[k,:] # Centroid c = self.center if ((x-c[0])**2+(y-c[1])**2) < self.radius**2: self.exchange_indices.append(k) if self.polygon is not None: # Inlet is polygon self.exchange_indices = inside_polygon(points, self.polygon) if self.exchange_indices is None: self.exchange_area = polygon_area(bounding_polygon) else: if len(self.exchange_indices) == 0: msg = 'No triangles have been identified in ' msg += 'specified region: %s' % inlet_region raise Exception(msg) # Compute exchange area as the sum of areas of triangles identified # by circle or polygon self.exchange_area = 0.0 for i in self.exchange_indices: self.exchange_area += domain.areas[i] msg = 'Exchange area in forcing term' msg += ' has area = %f' %self.exchange_area assert self.exchange_area > 0.0 # Check and store default_rate msg = ('Keyword argument default_rate must be either None ' 'or a function of time.\nI got %s.' % str(default_rate)) assert (default_rate is None or isinstance(default_rate, (int, float)) or callable(default_rate)), msg if default_rate is not None: # If it is a constant, make it a function if not callable(default_rate): tmp = default_rate default_rate = lambda t: tmp # Check that default_rate is a function of one argument try: default_rate(0.0) except: raise Exception(msg) self.default_rate = default_rate self.default_rate_invoked = False # Flag
def test_get_maximum_inundation_from_sww(self): """test_get_maximum_inundation_from_sww(self) Test of get_maximum_inundation_elevation() and get_maximum_inundation_location(). This is based on test_get_maximum_inundation_3(self) but works with the stored results instead of with the internal data structure. This test uses the underlying get_maximum_inundation_data for tests """ verbose = False from anuga.config import minimum_storable_height initial_runup_height = -0.4 final_runup_height = -0.3 filename = 'runup_test_2' #-------------------------------------------------------------- # Setup computational domain #-------------------------------------------------------------- N = 10 points, vertices, boundary = rectangular_cross(N, N) domain = Domain(points, vertices, boundary) domain.set_name(filename) domain.set_maximum_allowed_speed(1.0) #domain.set_minimum_storable_height(1.0e-5) domain.set_store_vertices_uniquely() # FIXME: This works better with old limiters so far domain.tight_slope_limiters = 0 #-------------------------------------------------------------- # Setup initial conditions #-------------------------------------------------------------- def topography(x, y): return -x/2 # linear bed slope # Use function for elevation domain.set_quantity('elevation', topography) domain.set_quantity('friction', 0.) # Zero friction # Constant negative initial stage domain.set_quantity('stage', initial_runup_height) #-------------------------------------------------------------- # Setup boundary conditions #-------------------------------------------------------------- Br = Reflective_boundary(domain) # Reflective wall Bd = Dirichlet_boundary([final_runup_height, 0, 0]) # Constant inflow # All reflective to begin with (still water) domain.set_boundary({'left': Br, 'right': Br, 'top': Br, 'bottom': Br}) #-------------------------------------------------------------- # Test initial inundation height #-------------------------------------------------------------- indices = domain.get_wet_elements() z = domain.get_quantity('elevation').\ get_values(location='centroids', indices=indices) assert num.alltrue(z < initial_runup_height) q_ref = domain.get_maximum_inundation_elevation(minimum_height=minimum_storable_height) # First order accuracy assert num.allclose(q_ref, initial_runup_height, rtol=1.0/N) #-------------------------------------------------------------- # Let triangles adjust #-------------------------------------------------------------- q_max = None for t in domain.evolve(yieldstep = 0.1, finaltime = 1.0): q = domain.get_maximum_inundation_elevation(minimum_height=minimum_storable_height) if verbose: domain.write_time() print q if q > q_max: q_max = q #-------------------------------------------------------------- # Test inundation height again #-------------------------------------------------------------- #q_ref = domain.get_maximum_inundation_elevation() q = get_maximum_inundation_elevation(filename+'.sww') msg = 'We got %f, should have been %f' % (q, q_max) assert num.allclose(q, q_max, rtol=2.0/N), msg msg = 'We got %f, should have been %f' % (q, initial_runup_height) assert num.allclose(q, initial_runup_height, rtol = 1.0/N), msg # Test error condition if time interval is out try: q = get_maximum_inundation_elevation(filename+'.sww', time_interval=[2.0, 3.0]) except ValueError: pass else: msg = 'should have caught wrong time interval' raise Exception, msg # Check correct time interval q, loc = get_maximum_inundation_data(filename+'.sww', time_interval=[0.0, 3.0]) msg = 'We got %f, should have been %f' % (q, initial_runup_height) assert num.allclose(q, initial_runup_height, rtol = 1.0/N), msg assert num.allclose(-loc[0]/2, q) # From topography formula #-------------------------------------------------------------- # Update boundary to allow inflow #-------------------------------------------------------------- domain.set_boundary({'right': Bd}) #-------------------------------------------------------------- # Evolve system through time #-------------------------------------------------------------- for t in domain.evolve(yieldstep = 0.1, finaltime = 3.0, skip_initial_step = True): q = domain.get_maximum_inundation_elevation(minimum_height=minimum_storable_height) if verbose: domain.write_time() print q if q > q_max: q_max = q #-------------------------------------------------------------- # Test inundation height again #-------------------------------------------------------------- indices = domain.get_wet_elements() z = domain.get_quantity('elevation').\ get_values(location='centroids', indices=indices) assert num.alltrue(z < final_runup_height+1.0/N) q = domain.get_maximum_inundation_elevation() # First order accuracy assert num.allclose(q, final_runup_height, rtol=1.0/N) q, loc = get_maximum_inundation_data(filename+'.sww', time_interval=[3.0, 3.0]) msg = 'We got %f, should have been %f' % (q, final_runup_height) assert num.allclose(q, final_runup_height, rtol=1.0/N), msg assert num.allclose(-loc[0]/2, q) # From topography formula q = get_maximum_inundation_elevation(filename+'.sww',verbose = verbose) loc = get_maximum_inundation_location(filename+'.sww') msg = 'We got %f, should have been %f' % (q, q_max) assert num.allclose(q, q_max, rtol=1.0/N), msg assert num.allclose(-loc[0]/2, q) # From topography formula q = get_maximum_inundation_elevation(filename+'.sww', time_interval=[0, 3]) msg = 'We got %f, should have been %f' % (q, q_max) assert num.allclose(q, q_max, rtol=1.0/N), msg # Check polygon mode # Runup region polygon = [[0.3, 0.0], [0.9, 0.0], [0.9, 1.0], [0.3, 1.0]] q = get_maximum_inundation_elevation(filename+'.sww', polygon = polygon, time_interval=[0, 3]) msg = 'We got %f, should have been %f' % (q, q_max) assert num.allclose(q, q_max, rtol=1.0/N), msg # Offshore region polygon = [[0.9, 0.0], [1.0, 0.0], [1.0, 1.0], [0.9, 1.0]] q, loc = get_maximum_inundation_data(filename+'.sww', polygon = polygon, time_interval=[0, 3]) msg = 'We got %f, should have been %f' % (q, -0.475) assert num.allclose(q, -0.475, rtol=1.0/N), msg assert is_inside_polygon(loc, polygon) assert num.allclose(-loc[0]/2, q) # From topography formula # Dry region polygon = [[0.0, 0.0], [0.4, 0.0], [0.4, 1.0], [0.0, 1.0]] q, loc = get_maximum_inundation_data(filename+'.sww', polygon = polygon, time_interval=[0, 3]) msg = 'We got %s, should have been None' % (q) assert q is None, msg msg = 'We got %s, should have been None' % (loc) assert loc is None, msg # Check what happens if no time point is within interval try: q = get_maximum_inundation_elevation(filename+'.sww', time_interval=[2.75, 2.75]) except AssertionError: pass else: msg = 'Time interval should have raised an exception' raise Exception, msg # Cleanup try: pass #os.remove(domain.get_name() + '.sww') except: pass
def _get_intersecting_segments(V, N, line, verbose=False): """Find edges intersected by line Input: V: Vertex coordinates as obtained by mesh.get_vertex_coordinates() N: Number of triangles in mesh line - list of two points forming a segmented line verbose Output: list of instances of class Triangle_intersection This method is used by the public method get_intersecting_segments(self, polyline) which also contains more documentation. """ from anuga.geometry.polygon import intersection from anuga.geometry.polygon import is_inside_polygon msg = 'Line segment must contain exactly two points' assert len(line) == 2, msg # Origin of intersecting line to be used for # establishing direction xi0 = line[0][0] eta0 = line[0][1] # Check intersection with edge segments for all triangles # FIXME (Ole): This should be implemented in C triangle_intersections={} # Keep track of segments already done for i in range(N): # Get nodes and edge segments for each triangle x0, y0 = V[3*i, :] x1, y1 = V[3*i+1, :] x2, y2 = V[3*i+2, :] edge_segments = [[[x0,y0], [x1, y1]], [[x1,y1], [x2, y2]], [[x2,y2], [x0, y0]]] # Find segments that are intersected by line intersections = {} # Use dictionary to record points only once for edge in edge_segments: status, value = intersection(line, edge) #if value is not None: log.critical('Triangle %d, status=%s, ' # 'value=%s' # % (i, str(status), str(value))) if status == 1: # Normal intersection of one edge or vertex intersections[tuple(value)] = i # Exclude singular intersections with vertices #if not(allclose(value, edge[0]) or\ # allclose(value, edge[1])): # intersections.append(value) if status == 2: # Edge is sharing a segment with line # This is usually covered by the two # vertices that would have been picked up # under status == 1. # However, if coinciding line stops partway # along this edge, it will be recorded here. intersections[tuple(value[0,:])] = i intersections[tuple(value[1,:])] = i if len(intersections) == 1: # Check if either line end point lies fully within this triangle # If this is the case accept that as one end of the intersecting # segment poly = V[3*i:3*i+3] if is_inside_polygon(line[1], poly, closed=False): intersections[tuple(line[1])] = i elif is_inside_polygon(line[0], poly, closed=False): intersections[tuple(line[0])] = i else: # Ignore situations where one vertex is touch, for instance continue msg = 'There can be only two or no intersections' assert len(intersections) in [0,2], msg if len(intersections) == 2: # Calculate attributes for this segment # End points of intersecting segment points = intersections.keys() x0, y0 = points[0] x1, y1 = points[1] # Determine which end point is closer to the origin of the line # This is necessary for determining the direction of # the line and the normals # Distances from line origin to the two intersections z0 = num.array([x0 - xi0, y0 - eta0], num.float) z1 = num.array([x1 - xi0, y1 - eta0], num.float) d0 = num.sqrt(num.sum(z0**2)) d1 = num.sqrt(num.sum(z1**2)) if d1 < d0: # Swap xi, eta = x0, y0 x0, y0 = x1, y1 x1, y1 = xi, eta # (x0,y0) is now the origin of the intersecting segment # Normal direction: # Right hand side relative to line direction vector = num.array([x1 - x0, y1 - y0], num.float) # Segment vector length = num.sqrt(num.sum(vector**2)) # Segment length normal = num.array([vector[1], -vector[0]], num.float)/length segment = ((x0,y0), (x1, y1)) T = Triangle_intersection(segment=segment, normal=normal, length=length, triangle_id=i) # Add segment unless it was done earlier if not triangle_intersections.has_key(segment): triangle_intersections[segment] = T # Return segments as a list return triangle_intersections.values()
def test_create_mesh_from_regions_with_caching(self): x = -500 y = -1000 mesh_geo = geo_reference = Geo_reference(56, x, y) # These are the absolute values polygon_absolute = [[0, 0], [100, 0], [100, 100], [0, 100]] x_p = -10 y_p = -40 geo_ref_poly = Geo_reference(56, x_p, y_p) polygon = geo_ref_poly.change_points_geo_ref(polygon_absolute) boundary_tags = {'walls': [0, 1], 'bom': [2, 3]} inner1_polygon_absolute = [[10, 10], [20, 10], [20, 20], [10, 20]] inner1_polygon = geo_ref_poly.\ change_points_geo_ref(inner1_polygon_absolute) inner2_polygon_absolute = [[30, 30], [40, 30], [40, 40], [30, 40]] inner2_polygon = geo_ref_poly.\ change_points_geo_ref(inner2_polygon_absolute) interior_regions = [(inner1_polygon, 5), (inner2_polygon, 10)] interior_holes = None # Clear cache first from anuga.caching import cache cache(_create_mesh_from_regions, (polygon, boundary_tags), { 'minimum_triangle_angle': 28.0, 'maximum_triangle_area': 10000000, 'interior_regions': interior_regions, 'interior_holes': interior_holes, 'poly_geo_reference': geo_ref_poly, 'mesh_geo_reference': mesh_geo, 'verbose': False }, verbose=False, clear=1) m = create_mesh_from_regions(polygon, boundary_tags, maximum_triangle_area=10000000, interior_regions=interior_regions, poly_geo_reference=geo_ref_poly, mesh_geo_reference=mesh_geo, verbose=False, use_cache=True) # Test the mesh instance self.assertTrue(len(m.regions) == 3, 'FAILED!') segs = m.getUserSegments() self.assertTrue(len(segs) == 12, 'FAILED!') self.assertTrue(len(m.userVertices) == 12, 'FAILED!') self.assertTrue(segs[0].tag == 'walls', 'FAILED!') self.assertTrue(segs[1].tag == 'walls', 'FAILED!') self.assertTrue(segs[2].tag == 'bom', 'FAILED!') self.assertTrue(segs[3].tag == 'bom', 'FAILED!') # Assuming the order of the region points is known. # (This isn't true, if you consider create_mesh_from_regions # a black box) poly_point = m.getRegions()[0] # poly_point values are relative to the mesh geo-ref # make them absolute self.assertTrue( is_inside_polygon([poly_point.x + x, poly_point.y + y], polygon_absolute, closed=False), 'FAILED!') # Assuming the order of the region points is known. # (This isn't true, if you consider create_mesh_from_regions # a black box) poly_point = m.getRegions()[1] # poly_point values are relative to the mesh geo-ref # make them absolute self.assertTrue( is_inside_polygon([poly_point.x + x, poly_point.y + y], inner1_polygon_absolute, closed=False), 'FAILED!') # Assuming the order of the region points is known. # (This isn't true, if you consider create_mesh_from_regions # a black box) poly_point = m.getRegions()[2] # poly_point values are relative to the mesh geo-ref # make them absolute self.assertTrue( is_inside_polygon([poly_point.x + x, poly_point.y + y], inner2_polygon_absolute, closed=False), 'FAILED!') # Now create m using cached values m_cache = create_mesh_from_regions(polygon, boundary_tags, 10000000, interior_regions=interior_regions, poly_geo_reference=geo_ref_poly, mesh_geo_reference=mesh_geo, verbose=False, use_cache=True)
def test_create_mesh_from_regions(self): x=-500 y=-1000 mesh_geo = geo_reference=Geo_reference(56, x, y) # These are the absolute values polygon_absolute = [[0,0], [100,0], [100,100], [0,100]] x_p = -10 y_p = -40 geo_ref_poly = Geo_reference(56, x_p, y_p) polygon = geo_ref_poly.change_points_geo_ref(polygon_absolute) boundary_tags = {'walls': [0,1], 'bom': [2,3]} inner1_polygon_absolute = [[10,10], [20,10], [20,20], [10,20]] inner1_polygon = geo_ref_poly.\ change_points_geo_ref(inner1_polygon_absolute) inner2_polygon_absolute = [[30,30], [40,30], [40,40], [30,40]] inner2_polygon = geo_ref_poly.\ change_points_geo_ref(inner2_polygon_absolute) interior_regions = [(inner1_polygon, 5), (inner2_polygon, 10)] m = create_mesh_from_regions(polygon, boundary_tags, 10000000, interior_regions=interior_regions, poly_geo_reference=geo_ref_poly, mesh_geo_reference=mesh_geo) # Test the mesh instance self.assertTrue(len(m.regions)==3, 'FAILED!') segs = m.getUserSegments() self.assertTrue(len(segs)==12, 'FAILED!') self.assertTrue(len(m.userVertices)==12, 'FAILED!') self.assertTrue(segs[0].tag=='walls', 'FAILED!') self.assertTrue(segs[1].tag=='walls', 'FAILED!') self.assertTrue(segs[2].tag=='bom', 'FAILED!') self.assertTrue(segs[3].tag=='bom', 'FAILED!') # Assuming the order of the region points is known. # (This isn't true, if you consider create_mesh_from_regions # a black box) poly_point = m.getRegions()[0] # poly_point values are relative to the mesh geo-ref # make them absolute msg = ('Expected point (%s,%s) to be inside polygon %s' % (str(poly_point.x+x), str(poly_point.y+y), str(polygon_absolute))) self.assertTrue(is_inside_polygon([poly_point.x+x, poly_point.y+y], polygon_absolute, closed=False), msg) # Assuming the order of the region points is known. # (This isn't true, if you consider create_mesh_from_regions # a black box) poly_point = m.getRegions()[1] # poly_point values are relative to the mesh geo-ref # make them absolute self.assertTrue(is_inside_polygon([poly_point.x+x, poly_point.y+y], inner1_polygon_absolute, closed=False), 'FAILED!') # Assuming the order of the region points is known. # (This isn't true, if you consider create_mesh_from_regions # a black box) poly_point = m.getRegions()[2] # poly_point values are relative to the mesh geo-ref # make them absolute self.assertTrue(is_inside_polygon([poly_point.x+x, poly_point.y+y], inner2_polygon_absolute, closed=False), 'FAILED!')
def test_create_mesh_from_regions_with_caching(self): x=-500 y=-1000 mesh_geo = geo_reference=Geo_reference(56, x, y) # These are the absolute values polygon_absolute = [[0,0], [100,0], [100,100], [0,100]] x_p = -10 y_p = -40 geo_ref_poly = Geo_reference(56, x_p, y_p) polygon = geo_ref_poly.change_points_geo_ref(polygon_absolute) boundary_tags = {'walls': [0,1], 'bom': [2,3]} inner1_polygon_absolute = [[10,10], [20,10], [20,20], [10,20]] inner1_polygon = geo_ref_poly.\ change_points_geo_ref(inner1_polygon_absolute) inner2_polygon_absolute = [[30,30], [40,30], [40,40], [30,40]] inner2_polygon = geo_ref_poly.\ change_points_geo_ref(inner2_polygon_absolute) interior_regions = [(inner1_polygon, 5), (inner2_polygon, 10)] interior_holes = None # Clear cache first from anuga.caching import cache cache(_create_mesh_from_regions, (polygon, boundary_tags), {'minimum_triangle_angle': 28.0, 'maximum_triangle_area': 10000000, 'interior_regions': interior_regions, 'interior_holes': interior_holes, 'poly_geo_reference': geo_ref_poly, 'mesh_geo_reference': mesh_geo, 'verbose': False}, verbose=False, clear=1) m = create_mesh_from_regions(polygon, boundary_tags, maximum_triangle_area=10000000, interior_regions=interior_regions, poly_geo_reference=geo_ref_poly, mesh_geo_reference=mesh_geo, verbose=False, use_cache=True) # Test the mesh instance self.assertTrue(len(m.regions)==3, 'FAILED!') segs = m.getUserSegments() self.assertTrue(len(segs)==12, 'FAILED!') self.assertTrue(len(m.userVertices)==12, 'FAILED!') self.assertTrue(segs[0].tag=='walls', 'FAILED!') self.assertTrue(segs[1].tag=='walls', 'FAILED!') self.assertTrue(segs[2].tag=='bom', 'FAILED!') self.assertTrue(segs[3].tag=='bom', 'FAILED!') # Assuming the order of the region points is known. # (This isn't true, if you consider create_mesh_from_regions # a black box) poly_point = m.getRegions()[0] # poly_point values are relative to the mesh geo-ref # make them absolute self.assertTrue(is_inside_polygon([poly_point.x+x, poly_point.y+y], polygon_absolute, closed=False), 'FAILED!') # Assuming the order of the region points is known. # (This isn't true, if you consider create_mesh_from_regions # a black box) poly_point = m.getRegions()[1] # poly_point values are relative to the mesh geo-ref # make them absolute self.assertTrue(is_inside_polygon([poly_point.x+x, poly_point.y+y], inner1_polygon_absolute, closed=False), 'FAILED!') # Assuming the order of the region points is known. # (This isn't true, if you consider create_mesh_from_regions # a black box) poly_point = m.getRegions()[2] # poly_point values are relative to the mesh geo-ref # make them absolute self.assertTrue(is_inside_polygon([poly_point.x+x, poly_point.y+y], inner2_polygon_absolute, closed=False), 'FAILED!') # Now create m using cached values m_cache = create_mesh_from_regions(polygon, boundary_tags, 10000000, interior_regions=interior_regions, poly_geo_reference=geo_ref_poly, mesh_geo_reference=mesh_geo, verbose=False, use_cache=True)
def test_create_mesh_from_regions(self): x = -500 y = -1000 mesh_geo = geo_reference = Geo_reference(56, x, y) # These are the absolute values polygon_absolute = [[0, 0], [100, 0], [100, 100], [0, 100]] x_p = -10 y_p = -40 geo_ref_poly = Geo_reference(56, x_p, y_p) polygon = geo_ref_poly.change_points_geo_ref(polygon_absolute) boundary_tags = {'walls': [0, 1], 'bom': [2, 3]} inner1_polygon_absolute = [[10, 10], [20, 10], [20, 20], [10, 20]] inner1_polygon = geo_ref_poly.\ change_points_geo_ref(inner1_polygon_absolute) inner2_polygon_absolute = [[30, 30], [40, 30], [40, 40], [30, 40]] inner2_polygon = geo_ref_poly.\ change_points_geo_ref(inner2_polygon_absolute) interior_regions = [(inner1_polygon, 5), (inner2_polygon, 10)] m = create_mesh_from_regions(polygon, boundary_tags, 10000000, interior_regions=interior_regions, poly_geo_reference=geo_ref_poly, mesh_geo_reference=mesh_geo) # Test the mesh instance self.assertTrue(len(m.regions) == 3, 'FAILED!') segs = m.getUserSegments() self.assertTrue(len(segs) == 12, 'FAILED!') self.assertTrue(len(m.userVertices) == 12, 'FAILED!') self.assertTrue(segs[0].tag == 'walls', 'FAILED!') self.assertTrue(segs[1].tag == 'walls', 'FAILED!') self.assertTrue(segs[2].tag == 'bom', 'FAILED!') self.assertTrue(segs[3].tag == 'bom', 'FAILED!') # Assuming the order of the region points is known. # (This isn't true, if you consider create_mesh_from_regions # a black box) poly_point = m.getRegions()[0] # poly_point values are relative to the mesh geo-ref # make them absolute msg = ('Expected point (%s,%s) to be inside polygon %s' % (str(poly_point.x + x), str(poly_point.y + y), str(polygon_absolute))) self.assertTrue( is_inside_polygon([poly_point.x + x, poly_point.y + y], polygon_absolute, closed=False), msg) # Assuming the order of the region points is known. # (This isn't true, if you consider create_mesh_from_regions # a black box) poly_point = m.getRegions()[1] # poly_point values are relative to the mesh geo-ref # make them absolute self.assertTrue( is_inside_polygon([poly_point.x + x, poly_point.y + y], inner1_polygon_absolute, closed=False), 'FAILED!') # Assuming the order of the region points is known. # (This isn't true, if you consider create_mesh_from_regions # a black box) poly_point = m.getRegions()[2] # poly_point values are relative to the mesh geo-ref # make them absolute self.assertTrue( is_inside_polygon([poly_point.x + x, poly_point.y + y], inner2_polygon_absolute, closed=False), 'FAILED!')
def test_get_maximum_inundation_from_sww(self): """test_get_maximum_inundation_from_sww(self) Test of get_maximum_inundation_elevation() and get_maximum_inundation_location(). This is based on test_get_maximum_inundation_3(self) but works with the stored results instead of with the internal data structure. This test uses the underlying get_maximum_inundation_data for tests """ verbose = False from anuga.config import minimum_storable_height initial_runup_height = -0.4 final_runup_height = -0.3 filename = 'runup_test_2' #-------------------------------------------------------------- # Setup computational domain #-------------------------------------------------------------- N = 10 points, vertices, boundary = rectangular_cross(N, N) domain = Domain(points, vertices, boundary) domain.set_low_froude(0) domain.set_name(filename) domain.set_maximum_allowed_speed(1.0) #domain.set_minimum_storable_height(1.0e-5) domain.set_store_vertices_uniquely() # FIXME: This works better with old limiters so far domain.tight_slope_limiters = 0 #-------------------------------------------------------------- # Setup initial conditions #-------------------------------------------------------------- def topography(x, y): return old_div(-x, 2) # linear bed slope # Use function for elevation domain.set_quantity('elevation', topography) domain.set_quantity('friction', 0.) # Zero friction # Constant negative initial stage domain.set_quantity('stage', initial_runup_height) #-------------------------------------------------------------- # Setup boundary conditions #-------------------------------------------------------------- Br = Reflective_boundary(domain) # Reflective wall Bd = Dirichlet_boundary([final_runup_height, 0, 0]) # Constant inflow # All reflective to begin with (still water) domain.set_boundary({'left': Br, 'right': Br, 'top': Br, 'bottom': Br}) #-------------------------------------------------------------- # Test initial inundation height #-------------------------------------------------------------- indices = domain.get_wet_elements() z = domain.get_quantity('elevation').\ get_values(location='centroids', indices=indices) assert num.alltrue(z < initial_runup_height) q_ref = domain.get_maximum_inundation_elevation( minimum_height=minimum_storable_height) # First order accuracy assert num.allclose(q_ref, initial_runup_height, rtol=1.0 / N) #-------------------------------------------------------------- # Let triangles adjust #-------------------------------------------------------------- q_max = None for t in domain.evolve(yieldstep=0.1, finaltime=1.0): q = domain.get_maximum_inundation_elevation( minimum_height=minimum_storable_height) if verbose: domain.write_time() print(q) if q is None and q_max is None: pass elif q_max is None or q > q_max: q_max = q else: pass #-------------------------------------------------------------- # Test inundation height again #-------------------------------------------------------------- #q_ref = domain.get_maximum_inundation_elevation() q = get_maximum_inundation_elevation(filename + '.sww') msg = 'We got %f, should have been %f' % (q, q_max) assert num.allclose(q, q_max, rtol=2.0 / N), msg msg = 'We got %f, should have been %f' % (q, initial_runup_height) assert num.allclose(q, initial_runup_height, rtol=1.0 / N), msg # Test error condition if time interval is out try: q = get_maximum_inundation_elevation(filename + '.sww', time_interval=[2.0, 3.0]) except ValueError: pass else: msg = 'should have caught wrong time interval' raise_(Exception, msg) # Check correct time interval q, loc = get_maximum_inundation_data(filename + '.sww', time_interval=[0.0, 3.0]) msg = 'We got %f, should have been %f' % (q, initial_runup_height) assert num.allclose(q, initial_runup_height, rtol=1.0 / N), msg assert num.allclose(old_div(-loc[0], 2), q) # From topography formula #-------------------------------------------------------------- # Update boundary to allow inflow #-------------------------------------------------------------- domain.set_boundary({'right': Bd}) #-------------------------------------------------------------- # Evolve system through time #-------------------------------------------------------------- for t in domain.evolve(yieldstep=0.1, finaltime=3.0, skip_initial_step=True): q = domain.get_maximum_inundation_elevation( minimum_height=minimum_storable_height) if verbose: domain.write_time() print(q) if q > q_max: q_max = q #-------------------------------------------------------------- # Test inundation height again #-------------------------------------------------------------- indices = domain.get_wet_elements() z = domain.get_quantity('elevation').\ get_values(location='centroids', indices=indices) assert num.alltrue(z < final_runup_height + 1.0 / N) q = domain.get_maximum_inundation_elevation() # First order accuracy assert num.allclose(q, final_runup_height, rtol=1.0 / N) q, loc = get_maximum_inundation_data(filename + '.sww', time_interval=[3.0, 3.0]) msg = 'We got %f, should have been %f' % (q, final_runup_height) assert num.allclose(q, final_runup_height, rtol=1.0 / N), msg assert num.allclose(old_div(-loc[0], 2), q) # From topography formula q = get_maximum_inundation_elevation(filename + '.sww', verbose=verbose) loc = get_maximum_inundation_location(filename + '.sww') msg = 'We got %f, should have been %f' % (q, q_max) assert num.allclose(q, q_max, rtol=1.0 / N), msg assert num.allclose(old_div(-loc[0], 2), q) # From topography formula q = get_maximum_inundation_elevation(filename + '.sww', time_interval=[0, 3]) msg = 'We got %f, should have been %f' % (q, q_max) assert num.allclose(q, q_max, rtol=1.0 / N), msg # Check polygon mode # Runup region polygon = [[0.3, 0.0], [0.9, 0.0], [0.9, 1.0], [0.3, 1.0]] q = get_maximum_inundation_elevation(filename + '.sww', polygon=polygon, time_interval=[0, 3]) msg = 'We got %f, should have been %f' % (q, q_max) assert num.allclose(q, q_max, rtol=1.0 / N), msg # Offshore region polygon = [[0.9, 0.0], [1.0, 0.0], [1.0, 1.0], [0.9, 1.0]] q, loc = get_maximum_inundation_data(filename + '.sww', polygon=polygon, time_interval=[0, 3]) msg = 'We got %f, should have been %f' % (q, -0.475) assert num.allclose(q, -0.475, rtol=1.0 / N), msg assert is_inside_polygon(loc, polygon) assert num.allclose(old_div(-loc[0], 2), q) # From topography formula # Dry region polygon = [[0.0, 0.0], [0.4, 0.0], [0.4, 1.0], [0.0, 1.0]] q, loc = get_maximum_inundation_data(filename + '.sww', polygon=polygon, time_interval=[0, 3]) msg = 'We got %s, should have been None' % (q) assert q is None, msg msg = 'We got %s, should have been None' % (loc) assert loc is None, msg # Check what happens if no time point is within interval try: q = get_maximum_inundation_elevation(filename + '.sww', time_interval=[2.75, 2.75]) except AssertionError: pass else: msg = 'Time interval should have raised an exception' raise_(Exception, msg) # Cleanup try: pass #os.remove(domain.get_name() + '.sww') except: pass