- Timestamp:
- Apr 1, 2009, 3:19:07 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/numpy/anuga/shallow_water/shallow_water_domain.py
r6553 r6689 812 812 813 813 return msg 814 814 815 816 817 def compute_boundary_flows(self): 818 """Compute boundary flows at current timestep. 819 820 Quantities computed are: 821 Total inflow across boundary 822 Total outflow across boundary 823 Flow across each tagged boundary segment 824 """ 825 826 # Run through boundary array and compute for each segment 827 # the normal momentum ((uh, vh) dot normal) times segment length. 828 # Based on sign accumulate this into boundary_inflow and boundary_outflow. 829 830 # Compute flows along boundary 831 832 uh = self.get_quantity('xmomentum').get_values(location='edges') 833 vh = self.get_quantity('ymomentum').get_values(location='edges') 834 835 # Loop through edges that lie on the boundary and calculate 836 # flows 837 boundary_flows = {} 838 total_boundary_inflow = 0.0 839 total_boundary_outflow = 0.0 840 for vol_id, edge_id in self.boundary: 841 # Compute normal flow across edge. Since normal vector points 842 # away from triangle, a positive sign means that water 843 # flows *out* from this triangle. 844 845 momentum = [uh[vol_id, edge_id], vh[vol_id, edge_id]] 846 normal = self.mesh.get_normal(vol_id, edge_id) 847 length = self.mesh.get_edgelength(vol_id, edge_id) 848 normal_flow = num.dot(momentum, normal)*length 849 850 # Reverse sign so that + is taken to mean inflow 851 # and - means outflow. This is more intuitive. 852 edge_flow = -normal_flow 853 854 # Tally up inflows and outflows separately 855 if edge_flow > 0: 856 # Flow is inflow 857 total_boundary_inflow += edge_flow 858 else: 859 # Flow is outflow 860 total_boundary_outflow += edge_flow 861 862 # Tally up flows by boundary tag 863 tag = self.boundary[(vol_id, edge_id)] 864 865 if tag not in boundary_flows: 866 boundary_flows[tag] = 0.0 867 boundary_flows[tag] += edge_flow 868 869 870 return boundary_flows, total_boundary_inflow, total_boundary_outflow 871 872 873 def compute_forcing_flows(self): 874 """Compute flows in and out of domain due to forcing terms. 875 876 Quantities computed are: 877 878 879 Total inflow through forcing terms 880 Total outflow through forcing terms 881 Current total volume in domain 882 883 """ 884 885 #FIXME(Ole): We need to separate what part of explicit_update was 886 # due to the normal flux calculations and what is due to forcing terms. 887 888 pass 889 890 891 def compute_total_volume(self): 892 """Compute total volume (m^3) of water in entire domain 893 """ 894 895 area = self.mesh.get_areas() 896 volume = 0.0 897 898 stage = self.get_quantity('stage').get_values(location='centroids') 899 elevation = self.get_quantity('elevation').get_values(location='centroids') 900 depth = stage-elevation 901 902 #print 'z', elevation 903 #print 'w', stage 904 #print 'h', depth 905 return num.sum(depth*area) 906 907 908 def volumetric_balance_statistics(self): 909 """Create volumetric balance report suitable for printing or logging. 910 """ 911 912 boundary_flows, total_boundary_inflow, total_boundary_outflow = self.compute_boundary_flows() 913 914 s = '---------------------------\n' 915 s += 'Volumetric balance report:\n' 916 s += '--------------------------\n' 917 s += 'Total boundary inflow [m^3/s]: %.2f\n' % total_boundary_inflow 918 s += 'Total boundary outflow [m^3/s]: %.2f\n' % total_boundary_outflow 919 s += 'Net boundary flow by tags [m^3/s]\n' 920 for tag in boundary_flows: 921 s += ' %s [m^3/s]: %.2f\n' % (tag, boundary_flows[tag]) 922 923 s += 'Total net boundary flow [m^3/s]: %.2f\n' % (total_boundary_inflow + total_boundary_outflow) 924 s += 'Total volume in domain [m^3]: %.2f\n' % self.compute_total_volume() 925 926 # The go through explicit forcing update and record the rate of change for stage and 927 # record into forcing_inflow and forcing_outflow. Finally compute integral 928 # of depth to obtain total volume of domain. 929 930 # FIXME(Ole): This part is not yet done. 931 932 return s 933 815 934 ################################################################################ 816 935 # End of class Shallow Water Domain … … 1386 1505 domain: pointer to shallow water domain for which the boundary applies 1387 1506 mean_stage: The mean water level which will be added to stage derived 1388 from the sww file1507 from the boundary condition 1389 1508 time_thinning: Will set how many time steps from the sww file read in 1390 1509 will be interpolated to the boundary. For example if … … 1402 1521 that available in the underlying data. 1403 1522 1523 Note that mean_stage will also be added to this. 1524 1404 1525 use_cache: 1405 1526 verbose: … … 1574 1695 xmom_update[k] += S*uh[k] 1575 1696 ymom_update[k] += S*vh[k] 1697 1698 def depth_dependent_friction(domain, default_friction, 1699 surface_roughness_data, 1700 verbose=False): 1701 """Returns an array of friction values for each wet element adjusted for depth. 1702 1703 Inputs: 1704 domain - computational domain object 1705 default_friction - depth independent bottom friction 1706 surface_roughness_data - N x 5 array of n0, d1, n1, d2, n2 values for each 1707 friction region. 1708 1709 Outputs: 1710 wet_friction - Array that can be used directly to update friction as follows: 1711 domain.set_quantity('friction', wet_friction) 1712 1713 1714 1715 """ 1716 1717 import Numeric as num 1718 1719 # Create a temp array to store updated depth dependent friction for wet elements 1720 # EHR this is outwardly inneficient but not obvious how to avoid recreating each call?????? 1721 N=len(domain) 1722 wet_friction = num.zeros(N, num.Float) 1723 wet_friction[:] = default_n0 # Initially assign default_n0 to all array so sure have no zeros values 1724 1725 1726 depth = domain.create_quantity_from_expression('stage - elevation') # create depth instance for this timestep 1727 # Recompute depth as vector 1728 d = depth.get_values(location='centroids') 1729 1730 # rebuild the 'friction' values adjusted for depth at this instant 1731 for i in domain.get_wet_elements(): # loop for each wet element in domain 1732 1733 # Get roughness data for each element 1734 n0 = float(surface_roughness_data[i,0]) 1735 d1 = float(surface_roughness_data[i,1]) 1736 n1 = float(surface_roughness_data[i,2]) 1737 d2 = float(surface_roughness_data[i,3]) 1738 n2 = float(surface_roughness_data[i,4]) 1739 1740 1741 # Recompute friction values from depth for this element 1742 1743 if d[i] <= d1: 1744 depth_dependent_friction = n1 1745 elif d[i] >= d2: 1746 depth_dependent_friction = n2 1747 else: 1748 depth_dependent_friction = n1+((n2-n1)/(d2-d1))*(d[i]-d1) 1749 1750 # check sanity of result 1751 if (depth_dependent_friction < 0.010 or depth_dependent_friction > 9999.0) : 1752 print model_data.basename+' >>>> WARNING: computed depth_dependent friction out of range ddf,n1,n2 ', depth_dependent_friction, n1,n2 1753 1754 # update depth dependent friction for that wet element 1755 wet_friction[i] = depth_dependent_friction 1756 1757 # EHR add code to show range of 'friction across domain at this instant as sanity check????????? 1758 1759 if verbose : 1760 nvals=domain.get_quantity('friction').get_values(location='centroids') # return array of domain nvals 1761 n_min=min(nvals) 1762 n_max=max(nvals) 1763 1764 print " ++++ calculate_depth_dependent_friction - Updated friction - range %7.3f to %7.3f" %(n_min,n_max) 1765 1766 return wet_friction 1767 1576 1768 1577 1769 ################################################################################ … … 1901 2093 assert is_inside_polygon(point, bounding_polygon), msg 1902 2094 1903 # Compute area and check that it is greater than 01904 self.exchange_area = polygon_area(self.polygon)1905 1906 msg = 'Polygon %s in forcing term' % str(self.polygon)1907 msg += ' has area = %f' % self.exchange_area1908 assert self.exchange_area > 0.01909 1910 2095 # Pointer to update vector 1911 2096 self.update = domain.quantities[self.quantity_name].explicit_update … … 1931 2116 if self.polygon is not None: 1932 2117 # Inlet is polygon 1933 inlet_region = ('polygon=\n%s, area=%f m^2' % 1934 (self.polygon, self.exchange_area)) 1935 2118 inlet_region = 'polygon=%s' % (self.polygon) 1936 2119 self.exchange_indices = inside_polygon(points, self.polygon) 1937 2120 1938 if self.exchange_indices is not None: 2121 if self.exchange_indices is None: 2122 self.exchange_area = polygon_area(bounding_polygon) 2123 else: 1939 2124 if len(self.exchange_indices) == 0: 1940 2125 msg = 'No triangles have been identified in ' … … 1942 2127 raise Exception, msg 1943 2128 2129 # Compute exchange area as the sum of areas of triangles identified 2130 # by circle or polygon 2131 self.exchange_area = 0.0 2132 for i in self.exchange_indices: 2133 self.exchange_area += domain.areas[i] 2134 2135 2136 msg = 'Exchange area in forcing term' 2137 msg += ' has area = %f' %self.exchange_area 2138 assert self.exchange_area > 0.0 2139 2140 2141 2142 1944 2143 # Check and store default_rate 1945 2144 msg = ('Keyword argument default_rate must be either None '
Note: See TracChangeset
for help on using the changeset viewer.