source: trunk/anuga_core/anuga/structures/inlet_operator.py @ 9737

Last change on this file since 9737 was 9705, checked in by steve, 10 years ago

Allow inlet_operators to run beyond time defined by file function

File size: 5.9 KB
Line 
1import anuga
2import numpy
3import inlet
4
5import warnings
6
7class Inlet_operator(anuga.Operator):
8    """Inlet Operator - add water to an inlet.
9    Sets up the geometry of problem
10   
11    Inherit from this class (and overwrite
12    discharge_routine method for specific subclasses)
13   
14    Input: domain, Two points
15    """ 
16
17
18    def __init__(self,
19                 domain,
20                 region,
21                 Q = 0.0,
22                 velocity = None,
23                 default = 0.0,
24                 description = None,
25                 label = None,
26                 logging = False,
27                 verbose = False):
28
29
30        anuga.Operator.__init__(self, domain, description, label, logging, verbose)
31
32        self.inlet = inlet.Inlet(self.domain, region, verbose= verbose)
33
34        # should set this up to be a function of time and or space)
35        self.Q = Q
36
37        if velocity is not None:
38            assert len(velocity)==2
39
40        self.velocity = velocity
41
42        self.applied_Q = 0.0
43
44        self.set_default(default)
45
46        self.activate_logging()
47
48
49    def __call__(self):
50
51        timestep = self.domain.get_timestep()
52
53        t = self.domain.get_time()
54
55
56        # Need to run global command on all processors
57        current_volume = self.inlet.get_total_water_volume()
58        total_area = self.inlet.get_area()
59
60        assert current_volume >= 0.0
61
62        Q1 = self.update_Q(t)
63        Q2 = self.update_Q(t + timestep)
64
65
66        #print Q1,Q2
67        Q = 0.5*(Q1+Q2)
68        volume = Q*timestep
69
70        #print volume
71       
72        #print Q, volume
73
74        # store last discharge
75        self.applied_Q = Q
76 
77
78       
79        # Distribute positive volume so as to obtain flat surface otherwise
80        # just pull water off to have a uniform depth.
81        if volume >= 0.0 :
82            self.inlet.set_stages_evenly(volume)
83            self.domain.fractional_step_volume_integral+=volume
84            if self.velocity is not None:
85                depths = self.inlet.get_depths()
86                self.inlet.set_xmoms(self.inlet.get_xmoms()+depths*self.velocity[0])
87                self.inlet.set_ymoms(self.inlet.get_ymoms()+depths*self.velocity[1])
88        elif current_volume + volume >= 0.0 :
89            depth = (current_volume + volume)/total_area
90            self.inlet.set_depths(depth)
91            self.domain.fractional_step_volume_integral+=volume
92        else: #extracting too much water!
93            self.inlet.set_depths(0.0)
94            self.domain.fractional_step_volume_integral-=current_volume
95            self.applied_Q = current_volume/timestep
96
97            #msg =  'Requesting too much water to be removed from an inlet! \n'
98            #msg += 'current_water_volume = %5.2e Increment volume = %5.2e' % (current_volume, volume)
99
100
101
102    def update_Q(self, t):
103        """Allowing local modifications of Q
104        """
105        from anuga.fit_interpolate.interpolate import Modeltime_too_early, Modeltime_too_late
106       
107        if callable(self.Q):
108            try:
109                Q = self.Q(t)
110            except Modeltime_too_early, e:
111                Q = self.get_default(t,err_msg=e)
112            except Modeltime_too_late, e:
113                Q = self.get_default(t,err_msg=e)
114        else:
115            Q = self.Q
116
117        return Q   
118 
119    def statistics(self):
120
121
122        message  = '=====================================\n'
123        message += 'Inlet Operator: %s\n' % self.label
124        message += '=====================================\n'
125
126        message += 'Description\n'
127        message += '%s' % self.description
128        message += '\n'
129       
130        inlet = self.inlet
131
132        message += '-------------------------------------\n'
133        message +=  'Inlet\n' 
134        message += '-------------------------------------\n'
135
136        message += 'inlet triangle indices and centres\n'
137        message += '%s' % inlet.triangle_indices
138        message += '\n'
139           
140        message += '%s' % self.domain.get_centroid_coordinates()[inlet.triangle_indices]
141        message += '\n'
142
143        message += 'region\n'
144        message += '%s' % inlet
145        message += '\n'
146
147        message += '=====================================\n'
148
149        return message
150
151
152    def timestepping_statistics(self):
153
154        message = '---------------------------\n'
155        message += 'Inlet report for %s:\n' % self.label
156        message += '--------------------------\n'
157        message += 'Q [m^3/s]: %.2f\n' % self.applied_Q
158
159        return message
160
161
162    def set_default(self, default=None):
163       
164        """ Either leave default as None or change it into a function"""
165
166        if default is not None:
167            # If it is a constant, make it a function
168            if not callable(default):
169                tmp = default
170                default = lambda t: tmp
171
172            # Check that default_rate is a function of one argument
173            try:
174                default(0.0)
175            except:
176                msg = "could not call default"
177                raise Exception(msg)
178
179        self.default = default
180        self.default_invoked = False
181
182
183
184    def get_default(self,t, err_msg=' '):
185        """ Call get_default only if exception
186        Modeltime_too_late(msg) has been raised
187        """
188
189
190        # Pass control to default rate function
191        value = self.default(t)
192
193        if self.default_invoked is False:
194            # Issue warning the first time
195            msg = ('%s\n'
196                   'Instead I will use the default rate: %s\n'
197                   'Note: Further warnings will be suppressed'
198                   % (str(err_msg), str(self.default(t))))
199           
200            warnings.warn(msg)
201
202            # FIXME (Ole): Replace this crude flag with
203            # Python's ability to print warnings only once.
204            # See http://docs.python.org/lib/warning-filter.html
205            self.default_invoked = True
206
207        return value
208
209
210    def set_Q(self, Q):
211
212        self.Q = Q
213
214    def get_Q(self):
215
216        return self.Q
217
218
219    def get_inlet(self):
220
221        return self.inlet
222
223
Note: See TracBrowser for help on using the repository browser.