1 | """Class Domain - |
---|
2 | 1D interval domains for finite-volume computations of |
---|
3 | the shallow water wave equation. |
---|
4 | |
---|
5 | This module contains a specialisation of class Domain from module domain.py |
---|
6 | consisting of methods specific to the Shallow Water Wave Equation |
---|
7 | |
---|
8 | |
---|
9 | U_t + E_x = S |
---|
10 | |
---|
11 | where |
---|
12 | |
---|
13 | U = [w, uh] |
---|
14 | E = [uh, u^2h + gh^2/2] |
---|
15 | S represents source terms forcing the system |
---|
16 | (e.g. gravity, friction, wind stress, ...) |
---|
17 | |
---|
18 | and _t, _x, _y denote the derivative with respect to t, x and y respectiely. |
---|
19 | |
---|
20 | The quantities are |
---|
21 | |
---|
22 | symbol variable name explanation |
---|
23 | x x horizontal distance from origin [m] |
---|
24 | z elevation elevation of bed on which flow is modelled [m] |
---|
25 | h height water height above z [m] |
---|
26 | w stage absolute water level, w = z+h [m] |
---|
27 | u speed in the x direction [m/s] |
---|
28 | uh xmomentum momentum in the x direction [m^2/s] |
---|
29 | |
---|
30 | eta mannings friction coefficient [to appear] |
---|
31 | nu wind stress coefficient [to appear] |
---|
32 | |
---|
33 | The conserved quantities are w, uh |
---|
34 | |
---|
35 | For details see e.g. |
---|
36 | Christopher Zoppou and Stephen Roberts, |
---|
37 | Catastrophic Collapse of Water Supply Reservoirs in Urban Areas, |
---|
38 | Journal of Hydraulic Engineering, vol. 127, No. 7 July 1999 |
---|
39 | |
---|
40 | |
---|
41 | John Jakeman, Ole Nielsen, Stephen Roberts, Duncan Gray, Christopher Zoppou |
---|
42 | Geoscience Australia, 2006 |
---|
43 | """ |
---|
44 | |
---|
45 | import numpy |
---|
46 | |
---|
47 | from anuga_1d.base.generic_domain import Generic_domain |
---|
48 | |
---|
49 | #Shallow water domain |
---|
50 | class Sqpipe_domain(Generic_domain): |
---|
51 | |
---|
52 | def __init__(self, coordinates, conserved_quantities, forcing_terms = [], boundary = None, state = None, update_state_flag = True, bulk_modulus = 1.0, tagged_elements = None): |
---|
53 | |
---|
54 | evolved_quantities = ['area', 'discharge', 'elevation', 'height', 'velocity','width','top','stage'] |
---|
55 | other_quantities = ['friction'] |
---|
56 | Generic_domain.__init__(self, |
---|
57 | coordinates = coordinates, |
---|
58 | boundary = boundary, |
---|
59 | conserved_quantities = conserved_quantities, |
---|
60 | evolved_quantities = evolved_quantities, |
---|
61 | other_quantities = other_quantities, |
---|
62 | tagged_elements = tagged_elements) |
---|
63 | |
---|
64 | self.bulk_modulus = bulk_modulus |
---|
65 | |
---|
66 | # Allocate space for tracking state (if not provided) |
---|
67 | if (state is None): |
---|
68 | self.state = numpy.zeros(self.number_of_elements, numpy.int) |
---|
69 | else: |
---|
70 | self.state = state |
---|
71 | |
---|
72 | self.update_state_flag = update_state_flag |
---|
73 | |
---|
74 | # Get computational parameters |
---|
75 | from anuga_1d.config import minimum_allowed_height, g, h0, epsilon |
---|
76 | self.minimum_allowed_height = minimum_allowed_height |
---|
77 | self.g = g |
---|
78 | self.h0 = h0 |
---|
79 | self.epsilon = epsilon |
---|
80 | |
---|
81 | #forcing terms |
---|
82 | for f in forcing_terms: |
---|
83 | self.forcing_terms.append(f) |
---|
84 | |
---|
85 | #Stored output |
---|
86 | self.store = True |
---|
87 | self.format = 'sww' |
---|
88 | self.smooth = True |
---|
89 | |
---|
90 | #Evolve parametrs |
---|
91 | self.cfl = 1.0 |
---|
92 | |
---|
93 | #Reduction operation for get_vertex_values |
---|
94 | from anuga_1d.base.util import mean |
---|
95 | self.reduction = mean |
---|
96 | #self.reduction = min #Looks better near steep slopes |
---|
97 | |
---|
98 | self.quantities_to_be_stored = conserved_quantities |
---|
99 | |
---|
100 | self.__doc__ = 'sqpipe_domain' |
---|
101 | |
---|
102 | self.check_integrity() |
---|
103 | |
---|
104 | |
---|
105 | def set_quantities_to_be_stored(self, q): |
---|
106 | """Specify which quantities will be stored in the sww file. |
---|
107 | |
---|
108 | q must be either: |
---|
109 | - the name of a quantity |
---|
110 | - a list of quantity names |
---|
111 | - None |
---|
112 | |
---|
113 | In the two first cases, the named quantities will be stored at each |
---|
114 | yieldstep |
---|
115 | (This is in addition to the quantities elevation and friction) |
---|
116 | If q is None, storage will be switched off altogether. |
---|
117 | """ |
---|
118 | |
---|
119 | |
---|
120 | if q is None: |
---|
121 | self.quantities_to_be_stored = [] |
---|
122 | self.store = False |
---|
123 | return |
---|
124 | |
---|
125 | if isinstance(q, basestring): |
---|
126 | q = [q] # Turn argument into a list |
---|
127 | |
---|
128 | #Check correctness |
---|
129 | for quantity_name in q: |
---|
130 | msg = 'Quantity %s is not a valid conserved quantity' %quantity_name |
---|
131 | assert quantity_name in self.conserved_quantities, msg |
---|
132 | |
---|
133 | self.quantities_to_be_stored = q |
---|
134 | |
---|
135 | |
---|
136 | def check_integrity(self): |
---|
137 | if (len(self.state) != self.number_of_elements): |
---|
138 | raise Exception("state has invalid length") |
---|
139 | Generic_domain.check_integrity(self) |
---|
140 | |
---|
141 | def compute_fluxes(self): |
---|
142 | # Set initial timestep to a large value |
---|
143 | import sys |
---|
144 | timestep = float(sys.maxint) |
---|
145 | |
---|
146 | # Update state before computing flux (if necessary) |
---|
147 | if self.update_state_flag: |
---|
148 | self.update_state() |
---|
149 | |
---|
150 | # Import flux method and call it |
---|
151 | from anuga_1d.sqpipe.sqpipe_dual_fixed_width_a_d_comp_flux import compute_fluxes_ext |
---|
152 | self.flux_timestep = compute_fluxes_ext(timestep,self) |
---|
153 | |
---|
154 | def update_state(self): |
---|
155 | h = self.quantities['height'].centroid_values |
---|
156 | t = self.quantities['top'].centroid_values |
---|
157 | |
---|
158 | new_state = numpy.zeros_like(self.state) |
---|
159 | |
---|
160 | # Update boundary state |
---|
161 | new_state[0] = update_cell_state(0, [0, 1], h, t, self.state) |
---|
162 | N = self.number_of_elements-1 |
---|
163 | new_state[N] = update_cell_state(N, [N-1, N], h, t, self.state) |
---|
164 | |
---|
165 | # Update interior states |
---|
166 | for i in range(1, N-1): |
---|
167 | new_state[i] = update_cell_state(i, [i-1, i+1], h, t, self.state) |
---|
168 | |
---|
169 | self.state = new_state |
---|
170 | #self.state = numpy.where(h>=t, 1, 0) |
---|
171 | |
---|
172 | def distribute_to_vertices_and_edges(self): |
---|
173 | # Should be implemented by the derived class |
---|
174 | raise Exception("Not implemented") |
---|
175 | |
---|
176 | def evolve(self, yieldstep = None, finaltime = None, duration = None, |
---|
177 | skip_initial_step = False): |
---|
178 | """Specialisation of basic evolve method from parent class |
---|
179 | """ |
---|
180 | |
---|
181 | #Call basic machinery from parent class |
---|
182 | for t in Generic_domain.evolve(self, yieldstep, finaltime,duration, |
---|
183 | skip_initial_step): |
---|
184 | |
---|
185 | #Pass control on to outer loop for more specific actions |
---|
186 | yield(t) |
---|
187 | |
---|
188 | # Auxillary methods |
---|
189 | |
---|
190 | # Method to update the state of a cell |
---|
191 | # cell is the index of the cell to update |
---|
192 | # neighbours is a list of the indices of it's neighbours |
---|
193 | # (for boundary cells, this could include the cell itself) |
---|
194 | def update_cell_state(cell, neighbours, h, t, s): |
---|
195 | # If height is bigger than top, then pressurise |
---|
196 | if h[cell] >= t[cell]: |
---|
197 | return 1 |
---|
198 | else: |
---|
199 | # If the cell was pressurised, and all it's neighbours |
---|
200 | # are pressurised, it remains pressurised even though |
---|
201 | # height is less than top |
---|
202 | # Otherwise, it's free surface |
---|
203 | if all([s[i] for i in neighbours]): |
---|
204 | return s[cell] |
---|
205 | else: |
---|
206 | return 0 |
---|
207 | |
---|
208 | #=============== End of Shallow Water Domain =============================== |
---|