source: trunk/anuga_work/development/2010-projects/anuga_1d/sqpipe/sqpipe_domain.py @ 8253

Last change on this file since 8253 was 8253, checked in by paul, 12 years ago

sqpipe update_state now uses neighbouring states

File size: 6.9 KB
Line 
1"""Class Domain -
21D interval domains for finite-volume computations of
3the shallow water wave equation.
4
5This module contains a specialisation of class Domain from module domain.py
6consisting of methods specific to the Shallow Water Wave Equation
7
8
9U_t + E_x = S
10
11where
12
13U = [w, uh]
14E = [uh, u^2h + gh^2/2]
15S represents source terms forcing the system
16(e.g. gravity, friction, wind stress, ...)
17
18and _t, _x, _y denote the derivative with respect to t, x and y respectiely.
19
20The quantities are
21
22symbol    variable name    explanation
23x         x                horizontal distance from origin [m]
24z         elevation        elevation of bed on which flow is modelled [m]
25h         height           water height above z [m]
26w         stage            absolute water level, w = z+h [m]
27u                          speed in the x direction [m/s]
28uh        xmomentum        momentum in the x direction [m^2/s]
29
30eta                        mannings friction coefficient [to appear]
31nu                         wind stress coefficient [to appear]
32
33The conserved quantities are w, uh
34
35For details see e.g.
36Christopher Zoppou and Stephen Roberts,
37Catastrophic Collapse of Water Supply Reservoirs in Urban Areas,
38Journal of Hydraulic Engineering, vol. 127, No. 7 July 1999
39
40
41John Jakeman, Ole Nielsen, Stephen Roberts, Duncan Gray, Christopher Zoppou
42Geoscience Australia, 2006
43"""
44
45import numpy
46
47from anuga_1d.base.generic_domain import Generic_domain
48
49#Shallow water domain
50class 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)
194def 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 ===============================
Note: See TracBrowser for help on using the repository browser.