Changeset 5736
- Timestamp:
- Sep 5, 2008, 11:30:19 AM (16 years ago)
- Location:
- anuga_core/source/anuga
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
anuga_core/source/anuga/abstract_2d_finite_volumes/quantity.py
r5729 r5736 1012 1012 associated matrices will be reused to save time. 1013 1013 1014 The argument interpolation points must be given as either a list of absolute UTM coordinates or 1015 a geospatial data object. 1016 """ 1017 1018 # FIXME (Ole): Could do with an input check (should be generalised and used widely) 1019 # That will check that interpolation points is either a list of points, Nx2 array, or geospatial 1014 The argument interpolation points must be given as either a 1015 list of absolute UTM coordinates or a geospatial data object. 1016 """ 1017 1018 # FIXME (Ole): Could do with an input check (should be generalised 1019 # and used widely) 1020 # That will check that interpolation points is either a list of 1021 # points, Nx2 array, or geospatial 1020 1022 1021 1023 # Ensure points are converted to coordinates relative to mesh origin 1022 # FIXME (Ole): This could all be refactored using the 'change_points_geo_ref' method 1023 # of Class geo_reference. The purpose is to make interpolation points relative 1024 # FIXME (Ole): This could all be refactored using the 1025 # 'change_points_geo_ref' method of Class geo_reference. 1026 # The purpose is to make interpolation points relative 1024 1027 # to the mesh origin. 1025 1028 # … … 1034 1037 interpolation_points = ensure_numeric(interpolation_points) 1035 1038 1036 # Get internal (discontinuous) triangles for use with the interpolation object. 1039 1040 1041 # Get internal (discontinuous) triangles for use with the 1042 # interpolation object. 1037 1043 x, y, vertex_values, triangles = self.get_vertex_values(xy=True, 1038 1044 smooth=False) -
anuga_core/source/anuga/coordinate_transforms/geo_reference.py
r5730 r5736 212 212 assert points.shape[1] == 2, msg 213 213 214 214 215 # FIXME (Ole): Could also check if zone, xllcorner, yllcorner 216 # are identical in the two geo refs. 215 217 if points_geo_ref is not self: 216 #add point geo ref to points 218 # If georeferences are different 219 217 220 if not points_geo_ref is None: 221 # Convert points to absolute coordinates 218 222 points[:,0] += points_geo_ref.xllcorner 219 223 points[:,1] += points_geo_ref.yllcorner 220 224 221 # subtract primary geo ref from points225 # Make points relative to primary geo reference 222 226 points[:,0] -= self.xllcorner 223 227 points[:,1] -= self.yllcorner -
anuga_core/source/anuga/shallow_water/data_manager.py
r5734 r5736 6466 6466 kind = 'total', 6467 6467 verbose=False): 6468 """Obtain flow (m^3/s) perpendicular tospecified cross section.6468 """Obtain average energy head [m] across specified cross section. 6469 6469 6470 6470 Inputs: 6471 filename: Name of sww file6472 6471 polyline: Representation of desired cross section - it may contain 6473 6472 multiple sections allowing for complex shapes. Assume … … 6478 6477 6479 6478 Output: 6480 time: All stored times in sww file6481 Q: Average energy [m] across given segments for all stored times. 6482 6483 The average velocity is computed for each triangle intersected by the polyline6484 and averaged weigted by segment lengths. 6485 6486 The typical usage of this function would be to get average energy of flow in a channel,6487 and the polyline would then be a cross sectionperpendicular to the flow.6488 6489 6490 #FIXME (Ole) - need name for this energy reflecting that its dimensionis [m].6479 E: Average energy [m] across given segments for all stored times. 6480 6481 The average velocity is computed for each triangle intersected by 6482 the polyline and averaged weighted by segment lengths. 6483 6484 The typical usage of this function would be to get average energy of 6485 flow in a channel, and the polyline would then be a cross section 6486 perpendicular to the flow. 6487 6488 #FIXME (Ole) - need name for this energy reflecting that its dimension 6489 is [m]. 6491 6490 """ 6492 6491 … … 6501 6500 # Get values for quantities at each midpoint of poly line from sww file 6502 6501 X = get_interpolated_quantities_at_polyline_midpoints(filename, 6503 quantity_names=quantity_names, 6502 quantity_names=\ 6503 quantity_names, 6504 6504 polyline=polyline, 6505 6505 verbose=verbose) -
anuga_core/source/anuga/shallow_water/shallow_water_domain.py
r5730 r5736 384 384 """Get the total flow through an arbitrary poly line. 385 385 386 This is a run-time equivalent of the function with same name in data_manager.py 386 This is a run-time equivalent of the function with same name 387 in data_manager.py 387 388 388 389 Input: … … 410 411 midpoints = segment_midpoints(segments) 411 412 412 # FIXME (Ole): HACK - need to make midpoints Geospatial instances413 #midpoints = self.geo_reference.get_absolute(midpoints)414 415 413 # Make midpoints Geospatial instances 416 414 midpoints = ensure_geospatial(midpoints, self.geo_reference) … … 439 437 # Accumulate 440 438 total_flow += segment_flow 441 442 439 443 440 return total_flow 444 441 442 443 444 def get_energy_through_cross_section(self, polyline, 445 kind = 'total', 446 verbose=False): 447 """Obtain average energy head [m] across specified cross section. 448 449 Inputs: 450 polyline: Representation of desired cross section - it may contain 451 multiple sections allowing for complex shapes. Assume 452 absolute UTM coordinates. 453 Format [[x0, y0], [x1, y1], ...] 454 kind: Select which energy to compute. 455 Options are 'specific' and 'total' (default) 456 457 Output: 458 E: Average energy [m] across given segments for all stored times. 459 460 The average velocity is computed for each triangle intersected by 461 the polyline and averaged weighted by segment lengths. 462 463 The typical usage of this function would be to get average energy of 464 flow in a channel, and the polyline would then be a cross section 465 perpendicular to the flow. 466 467 #FIXME (Ole) - need name for this energy reflecting that its dimension 468 is [m]. 469 """ 470 471 from anuga.config import g, epsilon, velocity_protection as h0 472 473 474 # Adjust polyline to mesh spatial origin 475 polyline = self.geo_reference.get_relative(polyline) 476 477 # 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 483 # Get midpoints 484 midpoints = segment_midpoints(segments) 485 486 # Make midpoints Geospatial instances 487 midpoints = ensure_geospatial(midpoints, self.geo_reference) 488 489 # Compute energy 490 if verbose: print 'Computing %s energy' %kind 491 492 # Get interpolated values 493 stage = self.get_quantity('stage') 494 elevation = self.get_quantity('elevation') 495 xmomentum = self.get_quantity('xmomentum') 496 ymomentum = self.get_quantity('ymomentum') 497 498 w = stage.get_values(interpolation_points=midpoints) 499 z = elevation.get_values(interpolation_points=midpoints) 500 uh = xmomentum.get_values(interpolation_points=midpoints) 501 vh = ymomentum.get_values(interpolation_points=midpoints) 502 h = w-z # Depth 503 504 # Compute total length of polyline for use with weighted averages 505 total_line_length = 0.0 506 for segment in segments: 507 total_line_length += segment.length 508 509 # Compute and sum flows across each segment 510 average_energy=0.0 511 for i in range(len(w)): 512 513 # Average velocity across this segment 514 if h[i] > epsilon: 515 # Use protection against degenerate velocities 516 u = uh[i]/(h[i] + h0/h[i]) 517 v = vh[i]/(h[i] + h0/h[i]) 518 else: 519 u = v = 0.0 520 521 speed_squared = u*u + v*v 522 kinetic_energy = 0.5*speed_squared/g 523 524 if kind == 'specific': 525 segment_energy = h[i] + kinetic_energy 526 elif kind == 'total': 527 segment_energy = w[i] + kinetic_energy 528 else: 529 msg = 'Energy kind must be either "specific" or "total".' 530 msg += ' I got %s' %kind 531 532 533 # Add to weighted average 534 weigth = segments[i].length/total_line_length 535 average_energy += segment_energy*weigth 536 537 538 return average_energy 539 540 541 445 542 446 543 def check_integrity(self): … … 1533 1630 1534 1631 class General_forcing: 1535 """ Class General_forcing - general explicit forcing term for update of quantity1632 """General explicit forcing term for update of quantity 1536 1633 1537 1634 This is used by Inflow and Rainfall for instance … … 1541 1638 1542 1639 domain: ANUGA computational domain 1543 quantity_name: Name of quantity to update. It must be a known conserved quantity. 1640 quantity_name: Name of quantity to update. 1641 It must be a known conserved quantity. 1642 1544 1643 rate [?/s]: Total rate of change over the specified area. 1545 1644 This parameter can be either a constant or a … … 1625 1724 1626 1725 for point in periphery_points: 1627 msg = 'Point %s on periphery for forcing term did not' %(str(point))1628 msg += ' fall within the domain boundary.'1726 msg = 'Point %s on periphery for forcing term' %(str(point)) 1727 msg += ' did not fall within the domain boundary.' 1629 1728 assert is_inside_polygon(point, bounding_polygon), msg 1630 1729 … … 1635 1734 # Check that polygon lies within the mesh. 1636 1735 for point in self.polygon: 1637 msg = 'Point %s in polygon for forcing term did not' %(str(point))1638 msg += ' fall within the domain boundary.'1736 msg = 'Point %s in polygon for forcing term' %(str(point)) 1737 msg += ' did not fall within the domain boundary.' 1639 1738 assert is_inside_polygon(point, bounding_polygon), msg 1640 1641 1642 1643 1644 1739 1645 1740 1646 1741 # Pointer to update vector 1647 self.update = domain.quantities[self.quantity_name].explicit_update 1742 self.update = domain.quantities[self.quantity_name].explicit_update 1648 1743 1649 1744 # Determine indices in flow area … … 1661 1756 for k in range(N): 1662 1757 x, y = points[k,:] # Centroid 1663 if ((x-self.center[0])**2+(y-self.center[1])**2) < self.radius**2: 1758 1759 c = self.center 1760 if ((x-c[0])**2+(y-c[1])**2) < self.radius**2: 1664 1761 self.exchange_indices.append(k) 1665 1762 … … 1676 1773 1677 1774 if len(self.exchange_indices) == 0: 1678 msg = 'No triangles have been identified in specified region: %s' %inlet_region 1775 msg = 'No triangles have been identified in ' 1776 msg += 'specified region: %s' %inlet_region 1679 1777 raise Exception, msg 1680 1778 … … 1723 1821 """Return values for specified quantity restricted to opening 1724 1822 """ 1725 return self.domain.quantities[self.quantity_name].get_values(indices=self.exchange_indices) 1823 1824 q = self.domain.quantities[self.quantity_name] 1825 return q.get_values(indices=self.exchange_indices) 1726 1826 1727 1827 … … 1729 1829 """Set values for specified quantity restricted to opening 1730 1830 """ 1731 self.domain.quantities[self.quantity_name].set_values(val, indices=self.exchange_indices) 1831 1832 q = self.domain.quantities[self.quantity_name] 1833 q.set_values(val, indices=self.exchange_indices) 1732 1834 1733 1835 … … 1766 1868 How to put them in a run File... 1767 1869 1768 #------------------------------------------------------------------------ --1870 #------------------------------------------------------------------------ 1769 1871 # Setup specialised forcing terms 1770 #------------------------------------------------------------------------ --1872 #------------------------------------------------------------------------ 1771 1873 # This is the new element implemented by Ole and Rudy to allow direct 1772 1874 # input of Inflow in mm/s … … 1842 1944 1843 1945 1844 #------------------------------------------------------------------------ --1946 #------------------------------------------------------------------------ 1845 1947 # Setup specialised forcing terms 1846 #------------------------------------------------------------------------ --1948 #------------------------------------------------------------------------ 1847 1949 # This is the new element implemented by Ole to allow direct input 1848 1950 # of Inflow in m^3/s … … 1862 1964 polygon=None, 1863 1965 verbose=False): 1864 1865 1866 #msg = 'Class Inflow must have either center & radius or a polygon specified.'1867 #assert center is not None and radius is not None or\1868 # polygon is not None, msg1869 1966 1870 1967 … … 1882 1979 overriding version in descendant 1883 1980 1884 This one converts m^3/s to m/s which can be added directly to 'stage' in ANUGA 1981 This one converts m^3/s to m/s which can be added directly 1982 to 'stage' in ANUGA 1885 1983 """ 1886 1984 -
anuga_core/source/anuga/shallow_water/test_shallow_water_domain.py
r5730 r5736 1502 1502 assert allclose(Q, uh*width) 1503 1503 1504 1505 1506 def test_get_energy_through_cross_section_with_geo(self): 1507 """test_get_energy_through_cross_section(self): 1508 1509 Test that the total and specific energy through a cross section can be 1510 correctly obtained at run-time from the ANUGA domain. 1511 1512 This test creates a flat bed with a known flow through it and tests 1513 that the function correctly returns the expected energies. 1514 1515 The specifics are 1516 e = -1 m 1517 u = 2 m/s 1518 h = 2 m 1519 w = 3 m (width of channel) 1520 1521 q = u*h*w = 12 m^3/s 1522 1523 1524 This run tries it with georeferencing and with elevation = -1 1525 1526 """ 1527 1528 import time, os 1529 from Numeric import array, zeros, allclose, Float, concatenate 1530 from Scientific.IO.NetCDF import NetCDFFile 1531 1532 # Setup 1533 from mesh_factory import rectangular 1534 1535 # Create basic mesh (20m x 3m) 1536 width = 3 1537 length = 20 1538 t_end = 1 1539 points, vertices, boundary = rectangular(length, width, 1540 length, width) 1541 1542 # Create shallow water domain 1543 domain = Domain(points, vertices, boundary, 1544 geo_reference=Geo_reference(56,308500,6189000)) 1545 1546 domain.default_order = 2 1547 domain.set_quantities_to_be_stored(None) 1548 1549 1550 e = -1.0 1551 w = 1.0 1552 h = w-e 1553 u = 2.0 1554 uh = u*h 1555 1556 Br = Reflective_boundary(domain) # Side walls 1557 Bd = Dirichlet_boundary([w, uh, 0]) # 2 m/s across the 3 m inlet: 1558 1559 1560 # Initial conditions 1561 domain.set_quantity('elevation', e) 1562 domain.set_quantity('stage', w) 1563 domain.set_quantity('xmomentum', uh) 1564 domain.set_boundary( {'left': Bd, 'right': Bd, 'top': Br, 'bottom': Br}) 1565 1566 1567 # Interpolation points down the middle 1568 I = [[0, width/2.], 1569 [length/2., width/2.], 1570 [length, width/2.]] 1571 interpolation_points = domain.geo_reference.get_absolute(I) 1572 1573 # Shortcuts to quantites 1574 stage = domain.get_quantity('stage') 1575 xmomentum = domain.get_quantity('xmomentum') 1576 ymomentum = domain.get_quantity('ymomentum') 1577 1578 for t in domain.evolve(yieldstep=0.1, finaltime = t_end): 1579 # Check that quantities are they should be in the interior 1580 1581 w_t = stage.get_values(interpolation_points) 1582 uh_t = xmomentum.get_values(interpolation_points) 1583 vh_t = ymomentum.get_values(interpolation_points) 1584 1585 assert allclose(w_t, w) 1586 assert allclose(uh_t, uh) 1587 assert allclose(vh_t, 0.0) 1588 1589 1590 # Check energies through the middle 1591 for i in range(5): 1592 x = length/2. + i*0.23674563 # Arbitrary 1593 cross_section = [[x, 0], [x, width]] 1594 1595 cross_section = domain.geo_reference.get_absolute(cross_section) 1596 Es = domain.get_energy_through_cross_section(cross_section, 1597 kind='specific', 1598 verbose=False) 1599 1600 assert allclose(Es, h + 0.5*u*u/g) 1601 1602 Et = domain.get_energy_through_cross_section(cross_section, 1603 kind='total', 1604 verbose=False) 1605 assert allclose(Et, w + 0.5*u*u/g) 1504 1606 1505 1607
Note: See TracChangeset
for help on using the changeset viewer.