1 | """ |
---|
2 | |
---|
3 | Water flowing down a channel with a floodplain and a bridge |
---|
4 | |
---|
5 | """ |
---|
6 | |
---|
7 | #------------------------------------------------------------------------------ |
---|
8 | # Import necessary modules |
---|
9 | #------------------------------------------------------------------------------ |
---|
10 | # Import standard shallow water domain and standard boundaries. |
---|
11 | import anuga |
---|
12 | import numpy |
---|
13 | #from anuga_parallel.parallel_operator_factory import Inlet_operator, Boyd_box_operator |
---|
14 | #from anuga.parallel.parallel_operator_factory import Inlet_operator, Boyd_box_operator, Internal_boundary_operator |
---|
15 | from anuga.parallel.parallel_operator_factory import Inlet_operator, Boyd_box_operator, Internal_boundary_operator |
---|
16 | from anuga.parallel import distribute, myid, numprocs, finalize, barrier |
---|
17 | #from anuga.structures.internal_boundary_operator import Internal_boundary_operator |
---|
18 | from anuga.structures.internal_boundary_functions import hecras_internal_boundary_function |
---|
19 | |
---|
20 | #------------------------------------------------------------------------------ |
---|
21 | # Useful parameters for controlling this case |
---|
22 | #------------------------------------------------------------------------------ |
---|
23 | |
---|
24 | floodplain_length = 1000.0 # Model domain length |
---|
25 | floodplain_width = 30.0 # Model domain width |
---|
26 | floodplain_slope = 1./200. |
---|
27 | chan_initial_depth = 0.25 # Initial depth of water in the channel |
---|
28 | chan_bankfull_depth = 1.0 # Bankfull depth of the channel |
---|
29 | chan_width = 10.0 # Bankfull width of the channel |
---|
30 | bankwidth = 0.01 # Width of the bank regions -- note that these protrude into the channel |
---|
31 | man_n=0.045 # Manning's n |
---|
32 | l0 = 5.000 # Length scale associated with triangle side length in channel (min_triangle area = 0.5*l0^2) |
---|
33 | |
---|
34 | bridge_us = 520. |
---|
35 | bridge_ds = 480. |
---|
36 | |
---|
37 | assert chan_width < floodplain_width, \ |
---|
38 | ' ERROR: Channel width is greater than floodplain width' |
---|
39 | |
---|
40 | assert bankwidth < chan_width/2., \ |
---|
41 | 'ERROR: The bank width must be less than half the channel width' |
---|
42 | |
---|
43 | #------------------------------------------------------------------------------ |
---|
44 | # Setup computational domain |
---|
45 | #------------------------------------------------------------------------------ |
---|
46 | |
---|
47 | # Define boundary polygon -- in this case clockwise around the proposed boundary |
---|
48 | boundary_polygon = [ [0.,0.], |
---|
49 | [0., floodplain_length], |
---|
50 | [floodplain_width/2. - chan_width/2., floodplain_length], |
---|
51 | [floodplain_width/2. + chan_width/2., floodplain_length], |
---|
52 | [floodplain_width, floodplain_length], |
---|
53 | [floodplain_width, 0.], |
---|
54 | [floodplain_width/2. + chan_width/2., 0.], |
---|
55 | [floodplain_width/2. - chan_width/2., 0.] |
---|
56 | ] |
---|
57 | |
---|
58 | breakLines = { # Put breaklines around edge of channel [think it helps the numerics] |
---|
59 | 'n1': [[floodplain_width/2.0 - chan_width/2., floodplain_length, -999.+0.*floodplain_length*floodplain_slope], |
---|
60 | [floodplain_width/2.0 - chan_width/2., 0., -999.0]], |
---|
61 | 'n3': [[floodplain_width/2.0 + chan_width/2.0, floodplain_length-l0*0, -999.+0.*floodplain_slope*floodplain_length], |
---|
62 | [floodplain_width/2.0 + chan_width/2.0, l0*0, -999.]], |
---|
63 | # Put breaklines for bridge, so the edges are 'sharp' |
---|
64 | 'n4': [ [0., bridge_ds, -0.99], [floodplain_width, bridge_ds, -0.99]], |
---|
65 | 'n5': [ [0., bridge_us, -0.99], [floodplain_width, bridge_us, -0.99]], |
---|
66 | } |
---|
67 | |
---|
68 | regionPtAreas=[ [0.01, 0.01, 0.5*l0*l0*4], # lower-left |
---|
69 | [floodplain_width/2., 0.01, 0.5*l0*l0], # lower channel |
---|
70 | [floodplain_width-0.01, 0.01, 0.5*l0*l0*4], # lower_right |
---|
71 | [0.01, floodplain_length-0.01, 0.5*l0*l0*4], # upper_left |
---|
72 | [floodplain_width/2., floodplain_length-0.01, 0.5*l0*l0], # Upper_channel |
---|
73 | [floodplain_width-0.01, floodplain_length-0.01, 0.5*l0*l0*4], # upper_right |
---|
74 | # Bridge |
---|
75 | [floodplain_width/2., floodplain_length/2., 0.5*l0*l0], |
---|
76 | [floodplain_width-0.01, floodplain_length/2., 0.5*l0*l0], |
---|
77 | [floodplain_width+0.01, floodplain_length/2., 0.5*l0*l0], |
---|
78 | |
---|
79 | ] |
---|
80 | |
---|
81 | if(myid==0): |
---|
82 | # Define domain with appropriate boundary conditions |
---|
83 | anuga.create_mesh_from_regions(boundary_polygon, |
---|
84 | boundary_tags={'left': [0], |
---|
85 | 'top1': [1], |
---|
86 | 'chan_out': [2], |
---|
87 | 'top2': [3], |
---|
88 | 'right': [4], |
---|
89 | 'bottom1': [5], |
---|
90 | 'chan_in': [6], |
---|
91 | 'bottom2': [7] }, |
---|
92 | maximum_triangle_area = 1.0e+06, #0.5*l0*l0, |
---|
93 | minimum_triangle_angle = 28.0, |
---|
94 | filename = 'channel_floodplain1.msh', |
---|
95 | interior_regions = [ ], |
---|
96 | breaklines=breakLines.values(), |
---|
97 | regionPtArea=regionPtAreas, |
---|
98 | verbose=True) |
---|
99 | domain=anuga.create_domain_from_file('channel_floodplain1.msh') |
---|
100 | domain.set_name('channel_floodplain1') # Output name |
---|
101 | domain.set_flow_algorithm('DE1') |
---|
102 | else: |
---|
103 | domain=None |
---|
104 | |
---|
105 | barrier() |
---|
106 | domain=distribute(domain) |
---|
107 | barrier() |
---|
108 | |
---|
109 | domain.set_store_vertices_uniquely(True) |
---|
110 | |
---|
111 | #------------------------------------------------------------------------------ |
---|
112 | # |
---|
113 | # Setup initial conditions |
---|
114 | # |
---|
115 | #------------------------------------------------------------------------------ |
---|
116 | |
---|
117 | # Function for topography |
---|
118 | def topography(x, y): |
---|
119 | # Longitudinally sloping floodplain with channel in centre |
---|
120 | elev1= -y*floodplain_slope - chan_bankfull_depth*\ |
---|
121 | (x>(floodplain_width/2. - chan_width/2.))*\ |
---|
122 | (x<(floodplain_width/2. + chan_width/2.)) |
---|
123 | # Add banks |
---|
124 | if(bankwidth>0.0): |
---|
125 | leftbnk = floodplain_width/2. - chan_width/2. |
---|
126 | rightbnk = floodplain_width/2. + chan_width/2. |
---|
127 | # Left bank |
---|
128 | elev2 = elev1 + (chan_bankfull_depth \ |
---|
129 | - chan_bankfull_depth/bankwidth*(x - leftbnk))*\ |
---|
130 | (x>leftbnk)*(x < leftbnk + bankwidth) |
---|
131 | # Right bank |
---|
132 | elev2 = elev2 + (chan_bankfull_depth \ |
---|
133 | + chan_bankfull_depth/bankwidth*(x - rightbnk))*\ |
---|
134 | (x>rightbnk-bankwidth)*(x < rightbnk) |
---|
135 | |
---|
136 | if(bankwidth==0.0): |
---|
137 | elev2 = elev1 |
---|
138 | |
---|
139 | # Add bridge |
---|
140 | elev2=elev2*( (y<bridge_ds) + (y>bridge_us)) -1.0*( (y>=bridge_ds)*(y<=bridge_us)) |
---|
141 | |
---|
142 | return elev2 |
---|
143 | |
---|
144 | #Function for stage |
---|
145 | def stagetopo(x,y): |
---|
146 | return -y*floodplain_slope -chan_bankfull_depth + chan_initial_depth |
---|
147 | |
---|
148 | domain.set_quantity('elevation', topography, location='centroids') # Use function for elevation |
---|
149 | domain.set_quantity('friction', man_n) # Constant friction |
---|
150 | domain.set_quantity('stage', stagetopo) # Use function for stage |
---|
151 | |
---|
152 | domain.riverwallData.create_riverwalls(breakLines, |
---|
153 | default_riverwallPar = {'Qfactor': 0.65}, # Weir coefficient of 1.1 (0.65*default_value) |
---|
154 | output_dir='riverwall_text') |
---|
155 | |
---|
156 | # Define inlet operator |
---|
157 | flow_in_yval = 10.0 |
---|
158 | if True: |
---|
159 | line1 = [ [floodplain_width/2. - chan_width/2., flow_in_yval],\ |
---|
160 | [floodplain_width/2. + chan_width/2., flow_in_yval] \ |
---|
161 | ] |
---|
162 | Qdata = [3., 3., 3., 3., 3., 3., 4., 5., 6., 6., 6., 6., 6., 7., 8., 9., 10., 10., 10., 10., 10.,\ |
---|
163 | 11., 12., 13., 14., 15., 15., 15., 15., 16., 17., 18., 19., 20., 21., 23., 25.,\ |
---|
164 | 30., 35.,40., 45., 50., 55., 60., 65., 70., 70., 70., 70.]+10*[70.] |
---|
165 | |
---|
166 | dtQdata=300. |
---|
167 | def Qin(t): |
---|
168 | t_hour=t/dtQdata # Used for time index for Qdata |
---|
169 | indL=numpy.floor(t_hour).astype(int) |
---|
170 | indU=numpy.ceil(t_hour).astype(int) |
---|
171 | w1=(t_hour-1.0*indL) |
---|
172 | w2=(1.0*indU-t_hour) |
---|
173 | Qout=Qdata[indL]*w2+Qdata[indU]*w1 |
---|
174 | return Qout |
---|
175 | |
---|
176 | Inlet_operator(domain, line1, Qin) |
---|
177 | |
---|
178 | # Set up bridge |
---|
179 | bridge_in = [ [floodplain_width/2. - chan_width/2.+0.01, bridge_ds-0.01],\ |
---|
180 | [floodplain_width/2. + chan_width/2.-0.01, bridge_ds-0.01] ] |
---|
181 | bridge_out = [ [floodplain_width/2. - chan_width/2.+0.01, bridge_us+0.01],\ |
---|
182 | [floodplain_width/2. + chan_width/2.-0.01, bridge_us+0.01] ] |
---|
183 | |
---|
184 | hecras_discharge_function = hecras_internal_boundary_function( |
---|
185 | 'hecras_bridge_table_high_deck.csv', |
---|
186 | allow_sign_reversal=True) |
---|
187 | |
---|
188 | bridge = Internal_boundary_operator( |
---|
189 | domain, |
---|
190 | hecras_discharge_function, |
---|
191 | width=chan_width, |
---|
192 | height=1.3, |
---|
193 | end_points=None, |
---|
194 | exchange_lines=[bridge_in, bridge_out], |
---|
195 | invert_elevation=-3.5, |
---|
196 | enquiry_gap=0.01, |
---|
197 | use_velocity_head=False, |
---|
198 | smoothing_timescale=30.0, |
---|
199 | logging=True) |
---|
200 | |
---|
201 | #------------------------------------------------------------------------------ |
---|
202 | # |
---|
203 | # Setup boundary conditions |
---|
204 | # |
---|
205 | #------------------------------------------------------------------------------ |
---|
206 | |
---|
207 | Br = anuga.Reflective_boundary(domain) # Solid reflective wall |
---|
208 | Bt = anuga.Transmissive_boundary(domain) # Transmissive boundary |
---|
209 | |
---|
210 | |
---|
211 | Bout_sub = anuga.Dirichlet_boundary( \ |
---|
212 | [-floodplain_length*floodplain_slope - chan_bankfull_depth + \ |
---|
213 | chan_initial_depth, 0., 0.]) #An outflow boundary for subcritical steady flow |
---|
214 | |
---|
215 | def outflow_stage_boundary(t): |
---|
216 | return -floodplain_length*floodplain_slope \ |
---|
217 | + chan_initial_depth - chan_bankfull_depth |
---|
218 | |
---|
219 | Bout_tmss = anuga.shallow_water.boundaries.Transmissive_momentum_set_stage_boundary(domain, function = outflow_stage_boundary) |
---|
220 | |
---|
221 | domain.set_boundary({'left': Br, |
---|
222 | 'right': Br, |
---|
223 | 'top1': Bout_tmss, |
---|
224 | 'top2': Bout_tmss, |
---|
225 | 'bottom1': Br, |
---|
226 | 'bottom2': Br, |
---|
227 | 'chan_out': Bout_tmss, |
---|
228 | 'chan_in': Br}) |
---|
229 | |
---|
230 | |
---|
231 | #------------------------------------------------------------------------------ |
---|
232 | # |
---|
233 | # Evolve system through time |
---|
234 | # |
---|
235 | #------------------------------------------------------------------------------ |
---|
236 | |
---|
237 | barrier() |
---|
238 | |
---|
239 | for t in domain.evolve(yieldstep=10.0, finaltime=dtQdata*(len(Qdata)-2)): |
---|
240 | if(myid==0): |
---|
241 | print domain.timestepping_statistics() |
---|
242 | |
---|
243 | vol = domain.report_water_volume_statistics() |
---|
244 | |
---|
245 | barrier() |
---|
246 | |
---|
247 | # Run sww merge |
---|
248 | if( (myid==0) & (numprocs>1)): |
---|
249 | print 'Merging sww files: ', numprocs, myid |
---|
250 | #os.chdir(project.output_run) |
---|
251 | anuga.utilities.sww_merge.sww_merge_parallel('channel_floodplain1',np=numprocs,verbose=True,delete_old=True) |
---|
252 | |
---|
253 | barrier() |
---|
254 | finalize() |
---|