source: trunk/anuga_core/source/anuga/structures/boyd_box_operator.py @ 7996

Last change on this file since 7996 was 7996, checked in by habili, 14 years ago

Confirming if the correct Culvert Velocity is being used, that is the resultant of Delta_Total_Energy

File size: 12.6 KB
Line 
1from anuga.geometry.polygon import inside_polygon, polygon_area
2from anuga.config import g, velocity_protection
3import anuga.utilities.log as log
4import math
5
6import structure_operator
7
8class Boyd_box_operator(structure_operator.Structure_operator):
9    """Culvert flow - transfer water from one rectangular box to another.
10    Sets up the geometry of problem
11   
12    This is the base class for culverts. Inherit from this class (and overwrite
13    compute_discharge method for specific subclasses)
14   
15    Input: Two points, pipe_size (either diameter or width, height),
16    mannings_rougness,
17    """ 
18
19    def __init__(self,
20                 domain,
21                 end_point0, 
22                 end_point1,
23                 width,
24                 height=None,
25                 apron=None,
26                 manning=0.013,
27                 enquiry_gap=0.2,
28                 use_momentum_jet=True,
29                 use_velocity_head=True,
30                 description=None,
31                 verbose=False):
32                     
33        structure_operator.Structure_operator.__init__(self,
34                                                       domain,
35                                                       end_point0, 
36                                                       end_point1,
37                                                       width,
38                                                       height,
39                                                       apron,
40                                                       manning,
41                                                       enquiry_gap,
42                                                       description,
43                                                       verbose)           
44       
45        self.use_momentum_jet = use_momentum_jet
46        self.use_velocity_head = use_velocity_head
47       
48        self.culvert_length = self.get_culvert_length()
49        self.culvert_width = self.get_culvert_width()
50        self.culvert_height = self.get_culvert_height()
51
52
53        self.sum_loss = 0.0
54        self.max_velocity = 10.0
55        self.log_filename = None
56
57        self.inlets = self.get_inlets()
58
59
60        # Stats
61       
62        self.discharge = 0.0
63        self.velocity = 0.0
64       
65       
66    def __call__(self):
67       
68        timestep = self.domain.get_timestep()
69       
70        self.__determine_inflow_outflow()
71       
72        Q, barrel_speed, outlet_depth = self.__discharge_routine()
73
74        #inflow  = self.routine.get_inflow()
75        #outflow = self.routine.get_outflow()
76
77        old_inflow_height = self.inflow.get_average_height()
78        old_inflow_xmom = self.inflow.get_average_xmom()
79        old_inflow_ymom = self.inflow.get_average_ymom()
80           
81        if old_inflow_height > 0.0 :
82                Qstar = Q/old_inflow_height
83        else:
84                Qstar = 0.0
85
86        factor = 1.0/(1.0 + Qstar*timestep/self.inflow.get_area())
87
88        new_inflow_height = old_inflow_height*factor
89        new_inflow_xmom = old_inflow_xmom*factor
90        new_inflow_ymom = old_inflow_ymom*factor
91           
92
93        self.inflow.set_heights(new_inflow_height)
94
95        #inflow.set_xmoms(Q/inflow.get_area())
96        #inflow.set_ymoms(0.0)
97
98
99        self.inflow.set_xmoms(new_inflow_xmom)
100        self.inflow.set_ymoms(new_inflow_ymom)
101
102
103        loss = (old_inflow_height - new_inflow_height)*self.inflow.get_area()
104
105           
106        # set outflow
107        if old_inflow_height > 0.0 :
108                timestep_star = timestep*new_inflow_height/old_inflow_height
109        else:
110            timestep_star = 0.0
111
112           
113        outflow_extra_height = Q*timestep_star/self.outflow.get_area()
114        outflow_direction = - self.outflow.outward_culvert_vector
115        outflow_extra_momentum = outflow_extra_height*barrel_speed*outflow_direction
116           
117
118        gain = outflow_extra_height*self.outflow.get_area()
119           
120        #print Q, Q*timestep, barrel_speed, outlet_depth, Qstar, factor, timestep_star
121        #print '  ', loss, gain
122
123        # Stats
124        self.discharge  = Q#outflow_extra_height*self.outflow.get_area()/timestep
125        self.velocity = barrel_speed#self.discharge/outlet_depth/self.width
126
127        new_outflow_height = self.outflow.get_average_height() + outflow_extra_height
128
129        if self.use_momentum_jet :
130            # FIXME (SR) Review momentum to account for possible hydraulic jumps at outlet
131            #new_outflow_xmom = outflow.get_average_xmom() + outflow_extra_momentum[0]
132            #new_outflow_ymom = outflow.get_average_ymom() + outflow_extra_momentum[1]
133
134            new_outflow_xmom = barrel_speed*new_outflow_height*outflow_direction[0]
135            new_outflow_ymom = barrel_speed*new_outflow_height*outflow_direction[1]
136
137        else:
138            #new_outflow_xmom = outflow.get_average_xmom()
139            #new_outflow_ymom = outflow.get_average_ymom()
140
141            new_outflow_xmom = 0.0
142            new_outflow_ymom = 0.0
143
144
145        self.outflow.set_heights(new_outflow_height)
146        self.outflow.set_xmoms(new_outflow_xmom)
147        self.outflow.set_ymoms(new_outflow_ymom)
148
149
150    def __determine_inflow_outflow(self):
151        # Determine flow direction based on total energy difference
152
153        if self.use_velocity_head:
154            self.delta_total_energy = self.inlets[0].get_enquiry_total_energy() - self.inlets[1].get_enquiry_total_energy()
155        else:
156            self.delta_total_energy = self.inlets[0].get_enquiry_stage() - self.inlets[1].get_enquiry_stage()
157
158
159        self.inflow  = self.inlets[0]
160        self.outflow = self.inlets[1]
161       
162
163        if self.delta_total_energy < 0:
164            self.inflow  = self.inlets[1]
165            self.outflow = self.inlets[0]
166            self.delta_total_energy = -self.delta_total_energy
167
168   
169    def __discharge_routine(self):
170
171        local_debug ='false'
172       
173        if self.inflow.get_enquiry_height() > 0.01: #this value was 0.01:
174            if local_debug =='true':
175                log.critical('Specific E & Deltat Tot E = %s, %s'
176                             % (str(self.inflow.get_enquiry_specific_energy()),
177                                str(self.delta_total_energy)))
178                log.critical('culvert type = %s' % str(culvert_type))
179            # Water has risen above inlet
180
181            if self.log_filename is not None:
182                s = 'Specific energy  = %f m' % self.inflow.get_enquiry_specific_energy()
183                log_to_file(self.log_filename, s)
184
185            msg = 'Specific energy at inlet is negative'
186            assert self.inflow.get_enquiry_specific_energy() >= 0.0, msg
187
188            if self.use_velocity_head :
189                self.driving_energy = self.inflow.get_enquiry_specific_energy()
190            else:
191                self.driving_energy = self.inflow.get_enquiry_height()
192
193            height = self.culvert_height
194            width = self.culvert_width
195            flow_width = self.culvert_width
196            # intially assume the culvert flow is controlled by the inlet
197            # check unsubmerged and submerged condition and use Min Q
198            # but ensure the correct flow area and wetted perimeter are used
199            Q_inlet_unsubmerged = 0.544*g**0.5*width*self.driving_energy**1.50 # Flow based on Inlet Ctrl Inlet Unsubmerged
200            Q_inlet_submerged = 0.702*g**0.5*width*height**0.89*self.driving_energy**0.61  # Flow based on Inlet Ctrl Inlet Submerged
201
202            # FIXME(Ole): Are these functions really for inlet control?
203            if Q_inlet_unsubmerged < Q_inlet_submerged:
204                Q = Q_inlet_unsubmerged
205                dcrit = (Q**2/g/width**2)**0.333333
206                if dcrit > height:
207                    dcrit = height
208                    flow_area = width*dcrit
209                    perimeter= 2.0*(width+dcrit)
210                else: # dcrit < height
211                    flow_area = width*dcrit
212                    perimeter= 2.0*dcrit+width
213                outlet_culvert_depth = dcrit
214                case = 'Inlet unsubmerged Box Acts as Weir'
215            else: # Inlet Submerged but check internal culvert flow depth
216                Q = Q_inlet_submerged
217                dcrit = (Q**2/g/width**2)**0.333333
218                if dcrit > height:
219                    dcrit = height
220                    flow_area = width*dcrit
221                    perimeter= 2.0*(width+dcrit)
222                else: # dcrit < height
223                    flow_area = width*dcrit
224                    perimeter= 2.0*dcrit+width
225                outlet_culvert_depth = dcrit
226                case = 'Inlet submerged Box Acts as Orifice'
227
228            dcrit = (Q**2/g/width**2)**0.333333
229            # May not need this .... check if same is done above
230            outlet_culvert_depth = dcrit
231            if outlet_culvert_depth > height:
232                outlet_culvert_depth = height  # Once again the pipe is flowing full not partfull
233                flow_area = width*height  # Cross sectional area of flow in the culvert
234                perimeter = 2*(width+height)
235                case = 'Inlet CTRL Outlet unsubmerged PIPE PART FULL'
236            else:
237                flow_area = width * outlet_culvert_depth
238                perimeter = width+2*outlet_culvert_depth
239                case = 'INLET CTRL Culvert is open channel flow we will for now assume critical depth'
240            # Initial Estimate of Flow for Outlet Control using energy slope
241            #( may need to include Culvert Bed Slope Comparison)
242            hyd_rad = flow_area/perimeter
243            culvert_velocity = math.sqrt(self.delta_total_energy/((self.sum_loss/2/g)+(self.manning**2*self.culvert_length)/hyd_rad**1.33333))
244            Q_outlet_tailwater = flow_area * culvert_velocity
245           
246           
247            if self.delta_total_energy < self.driving_energy:
248                # Calculate flows for outlet control
249
250                # Determine the depth at the outlet relative to the depth of flow in the Culvert
251                if self.outflow.get_enquiry_height() > height:        # The Outlet is Submerged
252                    outlet_culvert_depth=height
253                    flow_area=width*height       # Cross sectional area of flow in the culvert
254                    perimeter=2.0*(width+height)
255                    case = 'Outlet submerged'
256                else:   # Here really should use the Culvert Slope to calculate Actual Culvert Depth & Velocity
257                    dcrit = (Q**2/g/width**2)**0.333333
258                    outlet_culvert_depth=dcrit   # For purpose of calculation assume the outlet depth = Critical Depth
259                    if outlet_culvert_depth > height:
260                        outlet_culvert_depth=height
261                        flow_area=width*height
262                        perimeter=2.0*(width+height)
263                        case = 'Outlet is Flowing Full'
264                    else:
265                        flow_area=width*outlet_culvert_depth
266                        perimeter=(width+2.0*outlet_culvert_depth)
267                        case = 'Outlet is open channel flow'
268
269                hyd_rad = flow_area/perimeter
270
271                if self.log_filename is not None:
272                    s = 'hydraulic radius at outlet = %f' % hyd_rad
273                    log_to_file(self.log_filename, s)
274
275                # Final Outlet control velocity using tail water
276                culvert_velocity = math.sqrt(self.delta_total_energy/((self.sum_loss/2/g)+(self.manning**2*self.culvert_length)/hyd_rad**1.33333))
277                Q_outlet_tailwater = flow_area * culvert_velocity
278
279                if self.log_filename is not None:
280                    s = 'Q_outlet_tailwater = %.6f' % Q_outlet_tailwater
281                    log_to_file(self.log_filename, s)
282                Q = min(Q, Q_outlet_tailwater)
283            else:
284                pass
285                #FIXME(Ole): What about inlet control?
286
287            culv_froude=math.sqrt(Q**2*flow_width/(g*flow_area**3))
288            if local_debug =='true':
289                log.critical('FLOW AREA = %s' % str(flow_area))
290                log.critical('PERIMETER = %s' % str(perimeter))
291                log.critical('Q final = %s' % str(Q))
292                log.critical('FROUDE = %s' % str(culv_froude))
293
294            # Determine momentum at the outlet
295            barrel_velocity = Q/(flow_area + velocity_protection/flow_area)
296
297        # END CODE BLOCK for DEPTH  > Required depth for CULVERT Flow
298
299        else: # self.inflow.get_enquiry_height() < 0.01:
300            Q = barrel_velocity = outlet_culvert_depth = 0.0
301
302        # Temporary flow limit
303        if barrel_velocity > self.max_velocity:
304            barrel_velocity = self.max_velocity
305            Q = flow_area * barrel_velocity
306
307        return Q, barrel_velocity, outlet_culvert_depth
308       
309       
310       
Note: See TracBrowser for help on using the repository browser.