Ignore:
Timestamp:
Apr 1, 2009, 3:19:07 PM (15 years ago)
Author:
rwilson
Message:

Back-merge from Numeric trunk to numpy branch.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/numpy/anuga/shallow_water/shallow_water_domain.py

    r6553 r6689  
    812812
    813813        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           
    815934################################################################################
    816935# End of class Shallow Water Domain
     
    13861505        domain: pointer to shallow water domain for which the boundary applies
    13871506        mean_stage: The mean water level which will be added to stage derived
    1388                     from the sww file
     1507                    from the boundary condition
    13891508        time_thinning: Will set how many time steps from the sww file read in
    13901509                       will be interpolated to the boundary. For example if
     
    14021521                          that available in the underlying data.
    14031522
     1523                          Note that mean_stage will also be added to this.
     1524                                               
    14041525        use_cache:
    14051526        verbose:
     
    15741695                xmom_update[k] += S*uh[k]
    15751696                ymom_update[k] += S*vh[k]
     1697
     1698def 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
    15761768
    15771769################################################################################
     
    19012093                assert is_inside_polygon(point, bounding_polygon), msg
    19022094
    1903             # Compute area and check that it is greater than 0
    1904             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_area
    1908             assert self.exchange_area > 0.0
    1909 
    19102095        # Pointer to update vector
    19112096        self.update = domain.quantities[self.quantity_name].explicit_update
     
    19312116        if self.polygon is not None:
    19322117            # 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)
    19362119            self.exchange_indices = inside_polygon(points, self.polygon)
    19372120
    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:   
    19392124            if len(self.exchange_indices) == 0:
    19402125                msg = 'No triangles have been identified in '
     
    19422127                raise Exception, msg
    19432128
     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           
    19442143        # Check and store default_rate
    19452144        msg = ('Keyword argument default_rate must be either None '
Note: See TracChangeset for help on using the changeset viewer.