source: trunk/anuga_work/development/gareth/tests/channel_floodplain/channel_floodplain1.py @ 8375

Last change on this file since 8375 was 8353, checked in by davies, 13 years ago

Updates to balanced_dev and associated tests

File size: 12.6 KB
Line 
1"""Simple water flow example using ANUGA
2Water flowing down a channel with a floodplain
3"""
4
5#------------------------------------------------------------------------------
6# Import necessary modules
7#------------------------------------------------------------------------------
8# Import standard shallow water domain and standard boundaries.
9import anuga
10import numpy
11from anuga.structures.inlet_operator import Inlet_operator
12from anuga import *
13#from swb_domain import domain
14#from anuga import *
15#from balanced_basic import *
16from balanced_dev import *
17#from balanced_basic.swb2_domain import *
18#from balanced_basic.swb2_domain import Domain
19#------------------------------------------------------------------------------
20# Useful parameters for controlling this case
21#------------------------------------------------------------------------------
22
23floodplain_length = 1000.0 # Model domain length
24floodplain_width = 14.0 # Model domain width
25floodplain_slope = 1./300.
26chan_initial_depth = 0.65 # Initial depth of water in the channel
27chan_bankfull_depth = 1.0 # Bankfull depth of the channel
28chan_width = 10.0 # Bankfull width of the channel
29bankwidth = 2. # Width of the bank regions -- note that these protrude into the channel
30man_n=0.03 # Manning's n
31l0 = 1.000 # Length scale associated with triangle side length in channel (min_triangle area = 0.5*l0^2)
32
33assert chan_width < floodplain_width, \
34        ' ERROR: Channel width is greater than floodplain width'
35
36assert bankwidth < chan_width/2., \
37        'ERROR: The bank width must be less than half the channel width'
38
39#------------------------------------------------------------------------------
40# Setup computational domain
41#------------------------------------------------------------------------------
42
43# Define boundary polygon -- in this case clockwise around the proposed boundary
44boundary_polygon = [ [0.,0.], 
45                     [0., floodplain_length], 
46                     [floodplain_width/2. - chan_width/2., floodplain_length], 
47                     [floodplain_width/2. + chan_width/2., floodplain_length], 
48                     [floodplain_width, floodplain_length], 
49                     [floodplain_width, 0.], 
50                     [floodplain_width/2. + chan_width/2., 0.], 
51                     [floodplain_width/2. - chan_width/2., 0.] 
52                     ]
53
54# Define channel polygon, where we can optionally refine the resolution.
55# Note that we set this a distance l0 inside the boundary polygon, so the polygons
56# do not overlap.
57channel_polygon = [ [floodplain_width/2. - chan_width/2., +l0],
58                    [floodplain_width/2. - chan_width/2., floodplain_length-l0],
59                    [floodplain_width/2. + chan_width/2., floodplain_length-l0],
60                    [floodplain_width/2. + chan_width/2., +l0]
61                    ]
62
63
64# Define domain with appropriate boundary conditions
65domain = create_domain_from_regions( boundary_polygon, 
66                                   boundary_tags={'left': [0],
67                                                  'top1': [1],
68                                                  'chan_out': [2],
69                                                  'top2': [3],
70                                                  'right': [4],
71                                                  'bottom1': [5],
72                                                  'chan_in': [6],
73                                                  'bottom2': [7] },
74                                   maximum_triangle_area = 0.5*l0*l0,
75                                   minimum_triangle_angle = 28.0,
76                                   mesh_filename = 'channel_floodplain1.msh',
77                                   interior_regions = [ ],
78                                   #interior_regions = [\
79                                   #    [channel_polygon, 0.5*l0*l0] ],
80                                   use_cache=False,
81                                   verbose=True)
82
83
84domain.set_name('channel_floodplain1_bal_dev_lowvisc') # Output name
85#domain.set_store_vertices_uniquely(True)
86#domain.use_edge_limiter=False
87#domain.extrapolate_velocity_second_order=False
88#------------------------------------------------------------------------------
89#
90# Setup initial conditions
91#
92#------------------------------------------------------------------------------
93
94# Function for topography
95def topography(x, y):
96    # Longitudinally sloping floodplain with channel in centre
97        #return -y*floodplain_slope -chan_bankfull_depth*\
98    #        (x>(floodplain_width/2. - chan_width/2.) )*\
99    #        (x<(floodplain_width/2. + chan_width/2.) )
100
101    elev1= -y*floodplain_slope - chan_bankfull_depth*\
102            (x>(floodplain_width/2. - chan_width/2.))*\
103            (x<(floodplain_width/2. + chan_width/2.)) 
104    # Add banks
105    if(bankwidth>0.0):
106        leftbnk = floodplain_width/2. - chan_width/2.
107        rightbnk = floodplain_width/2. + chan_width/2.
108        # Left bank
109        elev2 = elev1 + (chan_bankfull_depth \
110                - chan_bankfull_depth/bankwidth*(x - leftbnk))*\
111                (x>leftbnk)*(x < leftbnk + bankwidth)
112        # Right bank
113        elev2 = elev2 + (chan_bankfull_depth \
114                + chan_bankfull_depth/bankwidth*(x - rightbnk))*\
115                (x>rightbnk-bankwidth)*(x < rightbnk)
116   
117    if(bankwidth==0.0):
118        elev2 = elev1
119    #
120    return elev2
121
122#
123
124#Function for stage
125def stagetopo(x,y):
126    return -y*floodplain_slope -chan_bankfull_depth + chan_initial_depth
127
128domain.set_quantity('elevation', topography) # Use function for elevation
129domain.set_quantity('friction', man_n) # Constant friction
130domain.set_quantity('stage', stagetopo) # Use function for stage
131domain.set_minimum_allowed_height(0.01) #
132#def steady_uh_calc():
133#    # Calculate a boundary condition potentially suitable for steady state flows.
134#    uh = (chan_initial_depth**(4./3.)*man_n**(-2.)*floodplain_slope)**0.5\
135#            *chan_initial_depth  # (u) * h
136#    return uh
137#
138#momin = steady_uh_calc()
139#velin = momin/chan_initial_depth
140#
141#print 'momentum inflow is = ' + str(momin)
142
143# Define inlet operator
144flow_in_yval=100.0
145if True:
146    line1 = [ [floodplain_width/2. - chan_width/2., flow_in_yval],\
147              [floodplain_width/2. + chan_width/2., flow_in_yval] \
148              ]
149    Qin = 0.5*(floodplain_slope*(chan_width*chan_initial_depth)**2.*man_n**(-2.)\
150            *chan_initial_depth**(4./3.) )**0.5
151   
152    Inlet_operator(domain, line1, Qin)
153   
154    print 'Discharge in = ', Qin #,'Velocity at inlet should be ', Qin/(chan_width*chan_initial_depth), \
155            #'for rectangular channels, and approximately that for trapezoidal ones'
156#------------------------------------------------------------------------------
157#
158# Setup boundary conditions
159#
160#------------------------------------------------------------------------------
161
162# We wish to define one inflow boundary at the upstream head of the channel,
163# one at the outflow of the channel (e.g. transmissive)
164# one at the floodplain edges, excluding the downstream floodplain edge
165#(e.g. reflective)  and one at the downstream floodplain edge (e.g. transmissive)
166
167#Bin_sub = anuga.shallow_water.boundaries.Dirichlet_discharge_boundary(domain,\
168#    chan_initial_depth - chan_bankfull_depth , 0.) # An inflow for subcritical
169#flow
170#Bin_sup = anuga.shallow_water.boundaries.Dirichlet_discharge_boundary(domain, \
171#        chan_initial_depth - chan_bankfull_depth , steady_uh_calc()) # An inflow 
172#                                                                     # for
173#                                                                     #supercritical
174#                                                                     # flow
175#Bin_sub = anuga.Dirichlet_boundary([chan_initial_depth - chan_bankfull_depth , \
176#    0., 0.]) # An inflow for subcritical flow -- maybe should use transmissive
177             # boundary instead
178#Bin_sup = anuga.Dirichlet_boundary([chan_initial_depth - chan_bankfull_depth ,\
179#        0., steady_uh_calc()]) # An inflow for supercritical flow
180
181# Trial a novel boundary, which variously imposes 2 or 3 conserved variables
182# depending on the local characteristic speed
183#Bin_trial = anuga.shallow_water.boundaries.\
184#        Dirichlet_inflow_boundary_sub_or_super_critical(domain, \
185#                stage0=chan_initial_depth - chan_bankfull_depth, wh0 = momin,\
186#                href = chan_initial_depth)
187
188# Trial a set_stage_transmissive_momentum inflow boundary
189#def inflow_stage_boundary(t):
190#    return chan_initial_depth - chan_bankfull_depth
191
192# transmissive_momentum_set_stage
193#Bin_tmss = anuga.shallow_water.boundaries.Transmissive_momentum_set_stage_boundary(domain=domain, function = inflow_stage_boundary)
194
195Br = anuga.Reflective_boundary(domain) # Solid reflective wall
196Bt = anuga.Transmissive_boundary(domain) # Transmissive boundary
197
198
199Bout_sub = anuga.Dirichlet_boundary( \
200        [-floodplain_length*floodplain_slope - chan_bankfull_depth + \
201        chan_initial_depth, 0., 0.]) #An outflow boundary for subcritical steady flow
202
203def outflow_stage_boundary(t):
204    return -floodplain_length*floodplain_slope \
205            + chan_initial_depth - chan_bankfull_depth
206
207# Note that the outflow boundary may be slightly incorrect for the trapezoidal channel case,
208# or incorrect more generally if there are numerical problems. But, in the central regions of
209# the channel, this shouldn't really prevent us reaching steady, uniform flow.
210Bout_tmss = anuga.shallow_water.boundaries.Transmissive_momentum_set_stage_boundary(domain, function = outflow_stage_boundary) 
211
212domain.set_boundary({'left': Br, 
213                     'right': Br, 
214                     'top1': Bt, 
215                     'top2': Bt, 
216                     'bottom1': Br, 
217                     'bottom2': Br, 
218                     'chan_out': Bout_tmss, 
219                     'chan_in': Br})
220
221
222# To monitor the boundary conditions, let's find centroid points representing sub and super critical flows.
223#inpt = numpy.argmin( ( abs(domain.centroid_coordinates[:,0] - floodplain_width/2.) + \
224#        abs(domain.centroid_coordinates[:,1] - 0.0)  ) )
225#outpt = numpy.argmin( ( abs(domain.centroid_coordinates[:, 0] - floodplain_width/2.) +\
226#        abs(domain.centroid_coordinates[:, 1] - floodplain_length)  ) )
227
228#------------------------------------------------------------------------------
229#
230# Evolve system through time
231#
232#------------------------------------------------------------------------------
233
234for t in domain.evolve(yieldstep=2.0, finaltime=3200.0):
235    print domain.timestepping_statistics()
236    xx=domain.quantities['ymomentum'].centroid_values
237    dd=(domain.quantities['stage'].centroid_values - domain.quantities['elevation'].centroid_values)
238    dd=dd*(dd>0.)
239
240    tmp = xx/(dd+1.0e-06)*(dd>0.0)
241    print tmp.max(), tmp.argmax(), tmp.min(),  tmp.argmin()
242
243    # Compute flow through cross-section -- check that the inflow boundary condition is doing its job
244    # This also provides another useful steady-state check
245    if( numpy.floor(t/100.) == t/100. ):
246        print '#### COMPUTING FLOW THROUGH CROSS-SECTIONS########'
247        s1 = domain.get_flow_through_cross_section([[0., floodplain_length-300.0], [floodplain_width, floodplain_length-300.0]])
248        s2 = domain.get_flow_through_cross_section([[0., floodplain_length-1.0], [floodplain_width, floodplain_length-1.0]])
249       
250        print 'Cross sectional flows: ', s1, s2
251        print '$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$'
252
253    #vv = domain.get_flow_through_cross_section
254    #print domain.quantities['ymomentum'].get_integral()
255    #print 'Qin = ', Qin
256    #print domain.quantities['stage'].centroid_values[inpt]
257    #print domain.quantities['xmomentum'].centroid_values[inpt]
258    #print domain.quantities['ymomentum'].centroid_values[inpt]
259
260    # Alter inflow boundary for sub and super critical flow
261    # FIXME: Varying the inflow boundary conditions does not work well with the modified ANUGA
262    # (but works great with the standard ANUGA). Especially the supercritical inflow seems bad.
263    # With the modified ANUGA, they oscillate (I wonder if the results are better with a finer grid?)
264    #h= domain.quantities['stage'].centroid_values[inpt] - domain.quantities['elevation'].centroid_values[inpt]
265    #uh=domain.quantities['xmomentum'].centroid_values[inpt] 
266    #if( domain.g*h < (uh/h)**2):
267    #    domain.set_boundary({'chan_in': Bin_sup})
268    #else:
269    #    domain.set_boundary({'chan_in': Bin_sub})
270
271    # Alter outflow boundary for sub and super critical flow
272    #h=domain.quantities['stage'].centroid_values[outpt] - domain.quantities['elevation'].centroid_values[outpt]
273    #uh=domain.quantities['xmomentum'].centroid_values[outpt] 
274    #if( domain.g*h < (uh/h)**2):
275    #    domain.set_boundary({'chan_out': Bt})
276    #else:
277    #    domain.set_boundary({'chan_out': Bout_sub})
278
Note: See TracBrowser for help on using the repository browser.