1 | """Example of shallow water wave equation. |
---|
2 | |
---|
3 | Specific methods pertaining to the 2D shallow water equation |
---|
4 | are imported from shallow_water |
---|
5 | for use with the generic finite volume framework |
---|
6 | |
---|
7 | Conserved quantities are h, uh and vh stored as elements 0, 1 and 2 in the |
---|
8 | numerical vector named conserved_quantities. |
---|
9 | """ |
---|
10 | |
---|
11 | #------------------------------------------------------------------------------ |
---|
12 | # Import necessary modules |
---|
13 | #------------------------------------------------------------------------------ |
---|
14 | from anuga.abstract_2d_finite_volumes.mesh_factory import rectangular |
---|
15 | from anuga.shallow_water import Domain |
---|
16 | from anuga.shallow_water.shallow_water_domain import Reflective_boundary |
---|
17 | from anuga.shallow_water.shallow_water_domain import Dirichlet_boundary |
---|
18 | |
---|
19 | #------------------------------------------------------------------------------ |
---|
20 | # Setup computational domain |
---|
21 | #------------------------------------------------------------------------------ |
---|
22 | |
---|
23 | #N = 120 |
---|
24 | N = 40 |
---|
25 | points, vertices, boundary = rectangular(N, N) |
---|
26 | domain = Domain(points, vertices, boundary) |
---|
27 | domain.set_name('kitchen_sink') # Output name |
---|
28 | print 'Size', len(domain) |
---|
29 | |
---|
30 | |
---|
31 | #------------------------------------------------------------------------------ |
---|
32 | # Setup initial conditions |
---|
33 | #------------------------------------------------------------------------------ |
---|
34 | |
---|
35 | domain.set_quantity('elevation', 0.0) # Zero bed elevation |
---|
36 | domain.set_quantity('stage', 0.015) # Constant stage |
---|
37 | domain.set_quantity('friction', 0.005) # Constant friction |
---|
38 | |
---|
39 | |
---|
40 | #------------------------------------------------------------------------------ |
---|
41 | # Setup specialised forcing terms |
---|
42 | #------------------------------------------------------------------------------ |
---|
43 | |
---|
44 | class Inflow: |
---|
45 | """Class Inflow - general 'rain and drain' forcing term. |
---|
46 | |
---|
47 | Useful for implementing flows in and out of the domain. |
---|
48 | |
---|
49 | Inflow(center, radius, flow) |
---|
50 | |
---|
51 | center [m]: Coordinates at center of flow point |
---|
52 | radius [m]: Size of circular area |
---|
53 | flow [m/s]: Rate of change of quantity over the specified area. |
---|
54 | This parameter can be either a constant or a function of time. |
---|
55 | Positive values indicate inflow, |
---|
56 | negative values indicate outflow. |
---|
57 | |
---|
58 | Examples |
---|
59 | |
---|
60 | Inflow((0.7, 0.4), 0.07, -0.2) # Constant drain at 0.2 m/s. |
---|
61 | # This corresponds to a flow of |
---|
62 | # 0.07**2*pi*0.2 = 0.00314 m^3/s |
---|
63 | |
---|
64 | Inflow((0.5, 0.5), 0.001, lambda t: min(4*t, 5)) # Tap turning up to |
---|
65 | # a maximum inflow of |
---|
66 | # 5 m/s over the |
---|
67 | # specified area |
---|
68 | """ |
---|
69 | |
---|
70 | # FIXME (OLE): Add a polygon as an alternative. |
---|
71 | # FIXME (OLE): Generalise to all quantities |
---|
72 | |
---|
73 | def __init__(self, |
---|
74 | center=None, radius=None, |
---|
75 | flow=0.0, |
---|
76 | quantity_name = 'stage'): |
---|
77 | |
---|
78 | if center is not None and radius is not None: |
---|
79 | assert len(center) == 2 |
---|
80 | else: |
---|
81 | msg = 'Both center and radius must be specified' |
---|
82 | raise Exception, msg |
---|
83 | |
---|
84 | self.center = center |
---|
85 | self.radius = radius |
---|
86 | self.flow = flow |
---|
87 | self.quantity = domain.quantities[quantity_name].explicit_update |
---|
88 | |
---|
89 | |
---|
90 | def __call__(self, domain): |
---|
91 | |
---|
92 | # Determine indices in flow area |
---|
93 | if not hasattr(self, 'indices'): |
---|
94 | center = self.center |
---|
95 | radius = self.radius |
---|
96 | |
---|
97 | N = len(domain) |
---|
98 | self.indices = [] |
---|
99 | coordinates = domain.get_centroid_coordinates() |
---|
100 | for k in range(N): |
---|
101 | x, y = coordinates[k,:] # Centroid |
---|
102 | if ((x-center[0])**2+(y-center[1])**2) < radius**2: |
---|
103 | self.indices.append(k) |
---|
104 | |
---|
105 | # Update inflow |
---|
106 | if callable(self.flow): |
---|
107 | flow = self.flow(domain.get_time()) |
---|
108 | else: |
---|
109 | flow = self.flow |
---|
110 | |
---|
111 | for k in self.indices: |
---|
112 | self.quantity[k] += flow |
---|
113 | |
---|
114 | |
---|
115 | class Culvert_flow: |
---|
116 | """Culvert flow - transfer water from one hole to another |
---|
117 | """ |
---|
118 | |
---|
119 | def __init__(self, |
---|
120 | inflow_center=None, inflow_radius=None, |
---|
121 | outflow_center=None, outflow_radius=None, |
---|
122 | transfer_flow=None) |
---|
123 | |
---|
124 | self.inflow=Inflow(center=inflow_center, |
---|
125 | radius=inflow_radius, |
---|
126 | flow=transfer_flow) |
---|
127 | |
---|
128 | self.outflow=Inflow(center=outflow_center, |
---|
129 | radius=outflow_radius, |
---|
130 | flow=-transfer_flow) #!!! |
---|
131 | |
---|
132 | |
---|
133 | |
---|
134 | def __call__(self, domain): |
---|
135 | self.inflow(domain) |
---|
136 | self.outflow(domain) |
---|
137 | |
---|
138 | |
---|
139 | sink = Inflow(center=[0.7, 0.4], radius=0.0707, flow = 0.0) |
---|
140 | tap = Inflow(center=(0.5, 0.5), radius=0.0316, |
---|
141 | flow=lambda t: min(4*t, 5)) # Tap turning up |
---|
142 | |
---|
143 | |
---|
144 | domain.forcing_terms.append(tap) |
---|
145 | domain.forcing_terms.append(sink) |
---|
146 | |
---|
147 | #------------------------------------------------------------------------------ |
---|
148 | # Setup boundary conditions |
---|
149 | #------------------------------------------------------------------------------ |
---|
150 | |
---|
151 | Br = Reflective_boundary(domain) # Solid reflective wall |
---|
152 | domain.set_boundary({'left': Br, 'right': Br, 'top': Br, 'bottom': Br}) |
---|
153 | |
---|
154 | #------------------------------------------------------------------------------ |
---|
155 | # Evolve system through time |
---|
156 | #------------------------------------------------------------------------------ |
---|
157 | for t in domain.evolve(yieldstep = 0.01, finaltime = 15): |
---|
158 | domain.write_time() |
---|
159 | |
---|
160 | if domain.get_time() >= 4 and tap.flow != 0.0: |
---|
161 | print 'Turning tap off' |
---|
162 | tap.flow = 0.0 |
---|
163 | |
---|
164 | if domain.get_time() >= 3 and sink.flow < 0.0: |
---|
165 | print 'Turning drain on' |
---|
166 | sink.flow = -0.8 |
---|
167 | |
---|