def test_2(self):
        #end_point0=[307138.813,6193474]
        #end_point1=[307150.563,6193469]
        end_point0=[10., 5.]
        end_point1=[10., 10.]     
        width = 1
        height = 3.5 
        number_of_barrels=1

        P = create_culvert_polygons(end_point0,
                                    end_point1,
                                    width=width,   
                                    height=height,
                                    number_of_barrels=number_of_barrels)
        
        # Compute area and check that it is greater than 0
        for key1 in ['exchange_polygon0',
                    'exchange_polygon1']:
            polygon = P[key1]
            area = polygon_area(polygon)
            
            msg = 'Polygon %s ' % (polygon)
            msg += ' has area = %f' % area
            assert area > 0.0, msg

            for key2 in ['enquiry_point0', 'enquiry_point1']:
                point = P[key2]
                assert not inside_polygon(point, polygon)                        
    def test_2(self):
        #end_point0=[307138.813,6193474]
        #end_point1=[307150.563,6193469]
        end_point0 = [10., 5.]
        end_point1 = [10., 10.]
        width = 1
        height = 3.5
        number_of_barrels = 1

        P = create_culvert_polygons(end_point0,
                                    end_point1,
                                    width=width,
                                    height=height,
                                    number_of_barrels=number_of_barrels)

        # Compute area and check that it is greater than 0
        for key1 in ['exchange_polygon0', 'exchange_polygon1']:
            polygon = P[key1]
            area = polygon_area(polygon)

            msg = 'Polygon %s ' % (polygon)
            msg += ' has area = %f' % area
            assert area > 0.0, msg

            for key2 in ['enquiry_point0', 'enquiry_point1']:
                point = P[key2]
                assert not inside_polygon(point, polygon)
Exemple #3
0
def create_culvert_polygons(end_point0,
                            end_point1, 
                            width, height=None,
                            enquiry_gap_factor=0.2,
                            number_of_barrels=1):
    """Create polygons at the end of a culvert inlet and outlet.
    At either end two polygons will be created; one for the actual flow to pass through and one a little further away
    for enquiring the total energy at both ends of the culvert and transferring flow.

    Input (mandatory):
        end_point0 - one end of the culvert (x,y)
        end_point1 - other end of the culvert (x,y)        
        width - culvert width

    Input (optional):        
        height - culvert height, defaults to width making a square culvert
        enquiry_gap_factor - sets the distance to the enquiry point as fraction of the height
        number_of_barrels - number of identical pipes.
        
    Output:

        Dictionary of four polygons. The dictionary keys are:
            'exchange_polygon0' - polygon defining the flow area at end_point0
            'exchange_polygon1' - polygon defining the flow area at end_point1
            'enquiry_point0' - point beyond exchange_polygon0
            'enquiry_point1' - point beyond exchange_polygon1            
            'vector'
            'length'
            'normal'
    """    


    # Input check
    if height is None:
        height = width

    # Dictionary for calculated polygons
    culvert_polygons = {}
    

    # Calculate geometry
    x0, y0 = end_point0
    x1, y1 = end_point1

    dx = x1-x0
    dy = y1-y0

    vector = num.array([dx, dy])
    length = sqrt(num.sum(vector**2))

    # Adjust polygon width to number of barrels in this culvert
    width *= number_of_barrels
    
    
    # Unit direction vector and normal 
    vector /= length                 # Unit vector in culvert direction
    normal = num.array([-dy, dx])/length # Normal vector
    
    culvert_polygons['vector'] = vector
    culvert_polygons['length'] = length
    culvert_polygons['normal'] = normal    

    # Short hands
    w = 0.5*width*normal # Perpendicular vector of 1/2 width 
    h = height*vector    # Vector of length=height in the
                         # direction of the culvert
    gap = (1 + enquiry_gap_factor)*h 
                         

    # Build exchange polygon and enquiry point for opening 0
    p0 = end_point0 + w
    p1 = end_point0 - w
    p2 = p1 - h
    p3 = p0 - h
    culvert_polygons['exchange_polygon0'] = num.array([p0,p1,p2,p3])
    culvert_polygons['enquiry_point0'] = end_point0 - gap
    

    # Build exchange polygon and enquiry point for opening 1
    p0 = end_point1 + w
    p1 = end_point1 - w
    p2 = p1 + h
    p3 = p0 + h
    culvert_polygons['exchange_polygon1'] = num.array([p0,p1,p2,p3])
    culvert_polygons['enquiry_point1'] = end_point1 + gap  

    # Check that enquiry polygons are outside exchange polygons
    for key1 in ['exchange_polygon0',
                 'exchange_polygon1']:
        polygon = culvert_polygons[key1]
        area = polygon_area(polygon)
        
        msg = 'Polygon %s ' %(polygon)
        msg += ' has area = %f' % area
        assert area > 0.0, msg

        for key2 in ['enquiry_point0', 'enquiry_point1']:
            point = culvert_polygons[key2]
            msg = 'Enquiry point falls inside an enquiry point.'
            msg += 'Email [email protected]'
            assert not inside_polygon(point, polygon), msg

    # Return results
    return culvert_polygons
Exemple #4
0
    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