Changeset 5862


Ignore:
Timestamp:
Oct 24, 2008, 4:18:35 PM (15 years ago)
Author:
ole
Message:

Made get_intersecting_segments cacheable and used that
with get_energy_through_cross_section and similar functions.

This helped the culvert routine along heaps, but I still believe
the interpolation could be made much more efficient.

Location:
anuga_core/source/anuga
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • anuga_core/source/anuga/abstract_2d_finite_volumes/neighbour_mesh.py

    r5729 r5862  
    99
    1010from general_mesh import General_mesh
     11from anuga.caching import cache
    1112from math import pi, sqrt
    1213from Numeric import array, allclose
     
    904905
    905906
    906     def _get_intersecting_segments(self, line,
    907                                    verbose=False):
    908       """Find edges intersected by line
    909 
    910       Input:
    911           line - list of two points forming a segmented line
    912           verbose
    913       Output:
    914           list of instances of class Triangle_intersection
    915 
    916       This method is used by the public method
    917       get_intersecting_segments(self, polyline) which also contains
    918       more documentation.
    919       """
    920 
    921       from anuga.utilities.polygon import intersection
    922       from anuga.utilities.polygon import is_inside_polygon
    923      
    924       msg = 'Line segment must contain exactly two points'
    925       assert len(line) == 2, msg
    926 
    927       # Origin of intersecting line to be used for
    928       # establishing direction
    929       xi0 = line[0][0]
    930       eta0 = line[0][1]
    931 
    932      
    933       # Check intersection with edge segments for all triangles
    934       # FIXME (Ole): This should be implemented in C
    935       V = self.get_vertex_coordinates()
    936       N = len(self)
    937       triangle_intersections={} # Keep track of segments already done
    938       for i in range(N):
    939           # Get nodes and edge segments for each triangle
    940           x0, y0 = V[3*i, :]
    941           x1, y1 = V[3*i+1, :]
    942           x2, y2 = V[3*i+2, :]
    943            
    944 
    945           edge_segments = [[[x0,y0], [x1, y1]],
    946                             [[x1,y1], [x2, y2]],
    947                             [[x2,y2], [x0, y0]]]
    948 
    949           # Find segments that are intersected by line
    950          
    951           intersections = {} # Use dictionary to record points only once
    952           for edge in edge_segments:
    953 
    954               status, value = intersection(line, edge)
    955               #if value is not None: print 'Triangle %d, Got' %i, status, value
    956                  
    957               if status == 1:
    958                   # Normal intersection of one edge or vertex
    959                   intersections[tuple(value)] = i                 
    960 
    961                   # Exclude singular intersections with vertices
    962                   #if not(allclose(value, edge[0]) or\
    963                   #       allclose(value, edge[1])):
    964                   #    intersections.append(value)
    965 
    966               if status == 2:
    967                   # Edge is sharing a segment with line
    968 
    969                   # This is usually covered by the two
    970                   # vertices that would have been picked up
    971                   # under status == 1.
    972                   # However, if coinciding line stops partway
    973                   # along this edge, it will be recorded here.
    974                   intersections[tuple(value[0,:])] = i
    975                   intersections[tuple(value[1,:])] = i                                   
    976 
    977                  
    978           if len(intersections) == 1:
    979               # Check if either line end point lies fully within this triangle
    980               # If this is the case accept that as one end of the intersecting
    981               # segment
    982 
    983               poly = V[3*i:3*i+3]
    984               if is_inside_polygon(line[1], poly, closed=False):
    985                   intersections[tuple(line[1])] = i
    986               elif is_inside_polygon(line[0], poly, closed=False):
    987                   intersections[tuple(line[0])] = i         
    988               else:
    989                   # Ignore situations where one vertex is touch, for instance                   
    990                   continue
    991 
    992 
    993           msg = 'There can be only two or no intersections'
    994           assert len(intersections) in [0,2], msg
    995 
    996 
    997           if len(intersections) == 2:
    998 
    999               # Calculate attributes for this segment
    1000 
    1001 
    1002               # End points of intersecting segment
    1003               points = intersections.keys()
    1004               x0, y0 = points[0]
    1005               x1, y1 = points[1]
    1006 
    1007 
    1008               # Determine which end point is closer to the origin of the line
    1009               # This is necessary for determining the direction of
    1010               # the line and the normals
    1011 
    1012               # Distances from line origin to the two intersections
    1013               z0 = array([x0 - xi0, y0 - eta0])
    1014               z1 = array([x1 - xi0, y1 - eta0])             
    1015               d0 = sqrt(sum(z0**2))
    1016               d1 = sqrt(sum(z1**2))
    1017                  
    1018               if d1 < d0:
    1019                   # Swap
    1020                   xi, eta = x0, y0
    1021                   x0, y0 = x1, y1
    1022                   x1, y1 = xi, eta
    1023 
    1024               # (x0,y0) is now the origin of the intersecting segment
    1025                  
    1026 
    1027               # Normal direction:
    1028               # Right hand side relative to line direction
    1029               vector = array([x1 - x0, y1 - y0]) # Segment vector
    1030               length = sqrt(sum(vector**2))      # Segment length
    1031               normal = array([vector[1], -vector[0]])/length
    1032 
    1033 
    1034               segment = ((x0,y0), (x1, y1))   
    1035               T = Triangle_intersection(segment=segment,
    1036                                         normal=normal,
    1037                                         length=length,
    1038                                         triangle_id=i)
    1039 
    1040 
    1041               # Add segment unless it was done earlier
    1042               if not triangle_intersections.has_key(segment):   
    1043                   triangle_intersections[segment] = T
    1044 
    1045 
    1046       # Return segments as a list           
    1047       return triangle_intersections.values()
    1048 
    1049 
    1050907
    1051908    def get_intersecting_segments(self, polyline,
     909                                  use_cache=False,
    1052910                                  verbose=False):
    1053       """Find edges intersected by polyline
    1054 
    1055       Input:
    1056           polyline - list of points forming a segmented line
    1057           verbose
    1058 
    1059       Output:
    1060           list of instances of class Triangle_intersection
    1061 
    1062       The polyline may break inside any triangle causing multiple
    1063       segments per triangle - consequently the same triangle may
    1064       appear in several entries.
    1065 
    1066       If a polyline segment coincides with a triangle edge,
    1067       the the entire shared segment will be used.
    1068       Onle one of the triangles thus intersected will be used and that
    1069       is the first one encoutered.
    1070 
    1071       Intersections with single vertices are ignored.
    1072 
    1073       Resulting segments are unsorted
    1074       """
    1075 
    1076       msg = 'Polyline must contain at least two points'
    1077       assert len(polyline) >= 2, msg
    1078 
    1079       # For all segments in polyline
    1080       triangle_intersections = []
    1081       for i, point0 in enumerate(polyline[:-1]):
    1082 
    1083           point1 = polyline[i+1]
    1084           if verbose:
    1085               print 'Extracting mesh intersections from line:',
    1086               print '(%.2f, %.2f) - (%.2f, %.2f)' %(point0[0], point0[1],
    1087                                                     point1[0], point1[1])
    1088              
    1089          
    1090           line = [point0, point1]
    1091 
    1092           triangle_intersections += self._get_intersecting_segments(line)
    1093 
    1094 
    1095       return triangle_intersections
    1096  
    1097 
     911        """Find edges intersected by polyline
     912
     913        Input:
     914            polyline - list of points forming a segmented line
     915            use_cache
     916            verbose
     917
     918        Output:
     919            list of instances of class Triangle_intersection
     920
     921        The polyline may break inside any triangle causing multiple
     922        segments per triangle - consequently the same triangle may
     923        appear in several entries.
     924
     925        If a polyline segment coincides with a triangle edge,
     926        the the entire shared segment will be used.
     927        Onle one of the triangles thus intersected will be used and that
     928        is the first one encountered.
     929
     930        Intersections with single vertices are ignored.
     931
     932        Resulting segments are unsorted
     933        """
     934       
     935        V = self.get_vertex_coordinates()
     936        N = len(self)
     937       
     938        # Adjust polyline to mesh spatial origin
     939        polyline = self.geo_reference.get_relative(polyline)
     940
     941        if use_cache is True:
     942            segments = cache(get_intersecting_segments,
     943                             (V, N, polyline),
     944                             {'verbose': verbose},
     945                             verbose=verbose)
     946        else:                 
     947            segments = get_intersecting_segments(V, N, polyline,
     948                                                 verbose=verbose)
     949       
     950
     951        return segments
     952       
    1098953 
    1099954
     
    11491004        return s
    11501005
     1006       
     1007
     1008def _get_intersecting_segments(V, N, line,
     1009                               verbose=False):
     1010    """Find edges intersected by line
     1011
     1012    Input:
     1013        V: Vertex coordinates as obtained by mesh.get_vertex_coordinates()
     1014        N: Number of triangles in mesh
     1015        line - list of two points forming a segmented line
     1016        verbose
     1017    Output:
     1018        list of instances of class Triangle_intersection
     1019
     1020    This method is used by the public method
     1021    get_intersecting_segments(self, polyline) which also contains
     1022    more documentation.
     1023    """
     1024
     1025    from anuga.utilities.polygon import intersection
     1026    from anuga.utilities.polygon import is_inside_polygon
     1027 
     1028    msg = 'Line segment must contain exactly two points'
     1029    assert len(line) == 2, msg
     1030
     1031    # Origin of intersecting line to be used for
     1032    # establishing direction
     1033    xi0 = line[0][0]
     1034    eta0 = line[0][1]
     1035
     1036 
     1037    # Check intersection with edge segments for all triangles
     1038    # FIXME (Ole): This should be implemented in C
     1039    triangle_intersections={} # Keep track of segments already done
     1040    for i in range(N):
     1041        # Get nodes and edge segments for each triangle
     1042        x0, y0 = V[3*i, :]
     1043        x1, y1 = V[3*i+1, :]
     1044        x2, y2 = V[3*i+2, :]
     1045         
     1046
     1047        edge_segments = [[[x0,y0], [x1, y1]],
     1048                          [[x1,y1], [x2, y2]],
     1049                          [[x2,y2], [x0, y0]]]
     1050
     1051        # Find segments that are intersected by line
     1052       
     1053        intersections = {} # Use dictionary to record points only once
     1054        for edge in edge_segments:
     1055
     1056            status, value = intersection(line, edge)
     1057            #if value is not None: print 'Triangle %d, Got' %i, status, value
     1058               
     1059            if status == 1:
     1060                # Normal intersection of one edge or vertex
     1061                intersections[tuple(value)] = i                 
     1062
     1063                # Exclude singular intersections with vertices
     1064                #if not(allclose(value, edge[0]) or\
     1065                #       allclose(value, edge[1])):
     1066                #    intersections.append(value)
     1067
     1068            if status == 2:
     1069                # Edge is sharing a segment with line
     1070
     1071                # This is usually covered by the two
     1072                # vertices that would have been picked up
     1073                # under status == 1.
     1074                # However, if coinciding line stops partway
     1075                # along this edge, it will be recorded here.
     1076                intersections[tuple(value[0,:])] = i
     1077                intersections[tuple(value[1,:])] = i                                   
     1078
     1079               
     1080        if len(intersections) == 1:
     1081            # Check if either line end point lies fully within this triangle
     1082            # If this is the case accept that as one end of the intersecting
     1083            # segment
     1084
     1085            poly = V[3*i:3*i+3]
     1086            if is_inside_polygon(line[1], poly, closed=False):
     1087                intersections[tuple(line[1])] = i
     1088            elif is_inside_polygon(line[0], poly, closed=False):
     1089                intersections[tuple(line[0])] = i         
     1090            else:
     1091                # Ignore situations where one vertex is touch, for instance                   
     1092                continue
     1093
     1094
     1095        msg = 'There can be only two or no intersections'
     1096        assert len(intersections) in [0,2], msg
     1097
     1098
     1099        if len(intersections) == 2:
     1100
     1101            # Calculate attributes for this segment
     1102
     1103
     1104            # End points of intersecting segment
     1105            points = intersections.keys()
     1106            x0, y0 = points[0]
     1107            x1, y1 = points[1]
     1108
     1109
     1110            # Determine which end point is closer to the origin of the line
     1111            # This is necessary for determining the direction of
     1112            # the line and the normals
     1113
     1114            # Distances from line origin to the two intersections
     1115            z0 = array([x0 - xi0, y0 - eta0])
     1116            z1 = array([x1 - xi0, y1 - eta0])             
     1117            d0 = sqrt(sum(z0**2))
     1118            d1 = sqrt(sum(z1**2))
     1119               
     1120            if d1 < d0:
     1121                # Swap
     1122                xi, eta = x0, y0
     1123                x0, y0 = x1, y1
     1124                x1, y1 = xi, eta
     1125
     1126            # (x0,y0) is now the origin of the intersecting segment
     1127               
     1128
     1129            # Normal direction:
     1130            # Right hand side relative to line direction
     1131            vector = array([x1 - x0, y1 - y0]) # Segment vector
     1132            length = sqrt(sum(vector**2))      # Segment length
     1133            normal = array([vector[1], -vector[0]])/length
     1134
     1135
     1136            segment = ((x0,y0), (x1, y1))   
     1137            T = Triangle_intersection(segment=segment,
     1138                                      normal=normal,
     1139                                      length=length,
     1140                                      triangle_id=i)
     1141
     1142
     1143            # Add segment unless it was done earlier
     1144            if not triangle_intersections.has_key(segment):   
     1145                triangle_intersections[segment] = T
     1146
     1147
     1148    # Return segments as a list           
     1149    return triangle_intersections.values()
     1150
     1151
     1152def get_intersecting_segments(V, N, polyline,
     1153                              verbose=False):       
     1154    """Internal function to find edges intersected by Polyline
     1155   
     1156    Input:
     1157        V: Vertex coordinates as obtained by mesh.get_vertex_coordinates()
     1158        N: Number of triangles in mesh
     1159        polyline - list of points forming a segmented line       
     1160        verbose
     1161    Output:
     1162        list of instances of class Triangle_intersection
     1163
     1164    This method is used by the public method
     1165    get_intersecting_segments(self, polyline) which also contains
     1166    more documentation.   
     1167    """
     1168
     1169    msg = 'Polyline must contain at least two points'
     1170    assert len(polyline) >= 2, msg
     1171     
     1172     
     1173    # For all segments in polyline
     1174    triangle_intersections = []
     1175    for i, point0 in enumerate(polyline[:-1]):
     1176
     1177        point1 = polyline[i+1]
     1178        if verbose:
     1179            print 'Extracting mesh intersections from line:',
     1180            print '(%.2f, %.2f) - (%.2f, %.2f)' %(point0[0], point0[1],
     1181                                                  point1[0], point1[1])
     1182           
     1183        line = [point0, point1]
     1184        triangle_intersections += _get_intersecting_segments(V, N, line,
     1185                                                             verbose=verbose)
     1186
     1187
     1188    msg = 'No segments found'
     1189    assert len(triangle_intersections) > 0, msg
     1190     
     1191       
     1192    return triangle_intersections
     1193 
     1194
     1195   
     1196           
     1197       
    11511198def segment_midpoints(segments):
    11521199    """Calculate midpoints of all segments
  • anuga_core/source/anuga/abstract_2d_finite_volumes/quantity.py

    r5855 r5862  
    873873            # This variant will cause Mesh object to be recreated
    874874            # in fit_to_mesh thus doubling up on the neighbour structure
    875             coordinates = self.domain.get_nodes(absolute=True)
    876             triangles = self.domain.triangles      #FIXME
     875            nodes = self.domain.get_nodes(absolute=True)
     876            triangles = self.domain.triangles     
    877877            vertex_attributes = fit_to_mesh(filename,
    878                                             coordinates, triangles,
    879                                             mesh=None,                                           
     878                                            nodes, triangles,
     879                                            mesh=None,
    880880                                            alpha=alpha,
    881881                                            attribute_name=attribute_name,
     
    10541054        # Speed is also a consideration here.
    10551055       
     1056       
    10561057        if isinstance(interpolation_points, Geospatial_data):       
    10571058            # Ensure interpolation points are in absolute UTM coordinates
     
    10771078                           use_cache=True,
    10781079                           verbose=verbose)
     1080                           
    10791081
    10801082
  • anuga_core/source/anuga/culvert_flows/Test_Culvert_Flat_Water_Lev.py

    r5777 r5862  
    3030#------------------------------------------------------------------------------
    3131print 'Setting up domain'
    32 
    33 # Open file for storing some specific results...
    34 fid = open('Culvert_Headwall', 'w')
    3532
    3633length = 40.
     
    149146#------------------------------------------------------------------------------
    150147print 'Setting Boundary Conditions'
    151 #Bi = Dirichlet_boundary([0.5, 0.0, 0.0])          # Inflow based on Flow Depth (0.5m) and Approaching Momentum !!!
    152148Bi = Dirichlet_boundary([0.0, 0.0, 0.0])          # Inflow based on Flow Depth and Approaching Momentum !!!
    153149Br = Reflective_boundary(domain)              # Solid reflective wall
     
    157153domain.set_boundary({'left': Btus, 'right': Btds, 'top': Br, 'bottom': Br})
    158154
    159 #------------------------------------------------------------------------------
    160 # Setup Application of  specialised forcing terms
    161 #------------------------------------------------------------------------------
    162 print 'Setting up Forcing Terms if Required'
    163 # This is the new element implemented by Ole to allow direct input of Inflow in m^3/s
    164 #fixed_flow = Inflow(domain, center=(2.1, 2.1), radius=1.261566, flow=1.00)   #   Fixed Flow Value Over Area of 5m2 at 1m/s = 5m^3/s
    165 
    166 #            flow=file_function('Q/QPMF_Rot_Sub13.tms'))        # Read Time Series in  from File
    167 #             flow=lambda t: min(0.01*t, 0.01942))                             # Time Varying Function   Tap turning up         
    168 
    169 #domain.forcing_terms.append(fixed_flow)
    170 
    171 
    172 
    173 
    174155
    175156#------------------------------------------------------------------------------
    176157# Evolve system through time
    177158#------------------------------------------------------------------------------
    178 print 'STARTING EVOLVE ======>'
    179159
     160#for t in domain.evolve(yieldstep = 0.01, finaltime = 45):
     161#     if int(domain.time*100) % 100 == 0:
     162#            domain.write_time()
     163   
    180164
    181 for t in domain.evolve(yieldstep = 0.01, finaltime = 45):
    182      if int(domain.time*100) % 100 == 0:
    183              domain.write_time()
     165# Profiling code
     166import time
     167t0 = time.time()
    184168   
    185     #if domain.get_time() >= 4 and tap.flow != 0.0:
    186     #    print 'Turning tap off'
    187     #    tap.flow = 0.0
    188        
    189     #if domain.get_time() >= 3 and sink.flow < 0.0:
    190     #    print 'Turning drain on'
    191     #    sink.flow = -0.8       
    192     # Close
     169s = 'for t in domain.evolve(yieldstep = 0.5, finaltime = 2): domain.write_time()'
    193170
    194 fid.close()
     171import profile, pstats
     172FN = 'profile.dat'
    195173
     174profile.run(s, FN)
     175   
     176print 'That took %.2f seconds' %(time.time()-t0)
     177
     178S = pstats.Stats(FN)
     179#S.sort_stats('time').print_stats(20)
     180s = S.sort_stats('cumulative').print_stats(30)
     181
     182print s
  • anuga_core/source/anuga/culvert_flows/culvert_routines.py

    r5437 r5862  
    6161    if inlet.depth_trigger >= 0.01 and inlet.depth >= 0.01:
    6262        # Calculate driving energy
    63         E = inlet.specific_energy
     63        E = inlet.total_energy
    6464
    6565        s = 'Driving energy  = %f m' %E
  • anuga_core/source/anuga/fit_interpolate/interpolate.py

    r5855 r5862  
    463463       
    464464        # Build n x m interpolation matrix
    465         if verbose and len(self.outside_poly_indices) > 0:
     465        if verbose and len(outside_poly_indices) > 0:
    466466            print '\n WARNING: Points outside mesh boundary. \n'
    467467           
  • anuga_core/source/anuga/shallow_water/data_manager.py

    r5773 r5862  
    63776377    mesh, quantities, time = X
    63786378
    6379 
    6380     # Adjust polyline to mesh spatial origin
    6381     polyline = mesh.geo_reference.get_relative(polyline)
    6382    
    63836379    # Find all intersections and associated triangles.
    63846380    segments = mesh.get_intersecting_segments(polyline, verbose=verbose)
  • anuga_core/source/anuga/shallow_water/shallow_water_domain.py

    r5773 r5862  
    399399        """       
    400400       
    401         # Adjust polyline to mesh spatial origin
    402         polyline = self.geo_reference.get_relative(polyline)
    403        
    404401        # Find all intersections and associated triangles.
    405         segments = self.get_intersecting_segments(polyline, verbose=verbose)
    406 
    407         msg = 'No segments found'
    408         assert len(segments) > 0, msg
    409        
     402        segments = self.get_intersecting_segments(polyline,
     403                                                  use_cache=True,
     404                                                  verbose=verbose)
     405
    410406        # Get midpoints
    411407        midpoints = segment_midpoints(segments)       
     
    472468                                         
    473469       
    474         # Adjust polyline to mesh spatial origin
    475         polyline = self.geo_reference.get_relative(polyline)
    476        
    477470        # Find all intersections and associated triangles.
    478         segments = self.get_intersecting_segments(polyline, verbose=verbose)
    479 
    480         msg = 'No segments found'
    481         assert len(segments) > 0, msg
    482        
     471        segments = self.get_intersecting_segments(polyline,
     472                                                  use_cache=True,
     473                                                  verbose=verbose)
     474
    483475        # Get midpoints
    484476        midpoints = segment_midpoints(segments)       
  • anuga_core/source/anuga/shallow_water/test_shallow_water_domain.py

    r5736 r5862  
    60096009    suite = unittest.makeSuite(Test_Shallow_Water,'test')
    60106010
    6011     #suite = unittest.makeSuite(Test_Shallow_Water,'test_get_flow_through_cross_section_with_geo')   
     6011    #suite = unittest.makeSuite(Test_Shallow_Water,'test_get_energy_through_cross_section_with_g')   
    60126012    #suite = unittest.makeSuite(Test_Shallow_Water,'test_fitting_using_shallow_water_domain')   
    60136013    #suite = unittest.makeSuite(Test_Shallow_Water,'test_tight_slope_limiters')
Note: See TracChangeset for help on using the changeset viewer.