source: trunk/anuga_core/source/anuga_parallel/parallel_inlet_operator.py @ 8256

Last change on this file since 8256 was 8256, checked in by steve, 12 years ago

Got test_all working again

File size: 6.0 KB
Line 
1# To change this template, choose Tools | Templates
2# and open the template in the editor.
3
4import anuga
5import numpy
6import math
7import anuga.structures.inlet
8
9from anuga.utilities.system_tools import log_to_file
10from anuga.structures.inlet_operator import Inlet_operator
11import parallel_inlet
12import pypar
13
14class Parallel_Inlet_operator(Inlet_operator):
15    """Parallel Inlet Operator - add water to an inlet potentially
16    shared between different parallel domains.
17
18    Sets up the geometry of problem
19
20    Inherit from this class (and overwrite
21    discharge_routine method for specific subclasses)
22
23    Input: domain, line,
24    """
25
26    """
27    master_proc - index of the processor which coordinates all processors
28    associated with this inlet operator.
29    procs - list of all processors associated with this inlet operator
30   
31    """
32
33    def __init__(self,
34                 domain,
35                 line,
36                 Q = 0.0,
37                 description = None,
38                 label = None,
39                 logging = False,
40                 master_proc = 0,
41                 procs = None,
42                 verbose = False):
43
44        self.domain = domain
45        self.domain.set_fractional_step_operator(self)
46        self.line = numpy.array(line, dtype='d')
47        self.master_proc = master_proc
48
49        if procs is None:
50            self.procs = [self.master_proc]
51        else:
52            self.procs = procs
53
54        self.myid = pypar.rank()
55
56        # should set this up to be a function of time and or space)
57        self.Q = Q
58
59        if description == None:
60            self.description = ' '
61        else:
62            self.description = description
63
64
65        if label == None:
66            self.label = "inlet_%g" % Inlet_operator.counter + "_P" + str(self.myid)
67        else:
68            self.label = label + '_%g' % Inlet_operator.counter + "_P" + str(self.myid)
69
70
71        self.verbose = verbose
72
73        # Keep count of inlet operator
74
75        # Only master proc can update the static counter
76        if self.myid == master_proc:
77            Inlet_operator.counter += 1
78
79        self.enquiry_point = 0.5*(self.line[0] + self.line[1])
80
81        self.outward_vector = self.line
82        self.inlet = parallel_inlet.Parallel_Inlet(self.domain, self.line, master_proc = master_proc,
83                                                    procs = procs, verbose= verbose)
84        self.set_logging(logging)
85
86    def __call__(self):
87
88        volume = 0
89
90        # Only the master proc calculates the volume
91
92        if self.myid == self.master_proc:
93            timestep = self.domain.get_timestep()
94
95            t = self.domain.get_time()
96            Q1 = self.update_Q(t)
97            Q2 = self.update_Q(t + timestep)
98
99            volume = 0.5*(Q1+Q2)*timestep
100
101            assert 0.5*(Q1+Q2) >= 0.0, 'Q < 0: Water to be removed from an inlet!'
102
103            #print "Volume to be removed from Inlet = " + str(volume)
104
105        # Set stages evenly
106        self.inlet.set_stages_evenly(volume)
107
108
109    def update_Q(self, t):
110        """Virtual method allowing local modifications by writing an
111        overriding version in descendant
112        """
113        # Only one processor should call this function unless Q is parallelizable
114        if callable(self.Q):
115            Q = self.Q(t)[0]
116        else:
117            Q = self.Q
118
119        return Q
120
121    def statistics(self):
122        # WARNING: requires synchronization, must be called by all procs associated
123        # with this inlet
124
125        message = ''
126
127        inlet_stats = self.inlet.statistics()
128       
129
130        if self.myid == self.master_proc:
131            message  = '=======================================\n'
132            message += 'Parallel Inlet Operator: %s\n' % self.label
133            message += '=======================================\n'
134           
135            message += 'Description\n'
136            message += '%s' % self.description
137            message += '\n'
138
139            message += inlet_stats
140
141            message += '=====================================\n'
142
143        return message
144
145
146    def print_statistics(self):
147        # WARNING: requires synchronization, must be called by all procs associated
148        # with this inlet
149       
150        print self.statistics()
151
152
153    def print_timestepping_statistics(self):
154        # WARNING: Must be called by master proc to have any effect
155
156        if self.myid == self.master_proc:
157            message = '---------------------------------------------\n'
158            message += 'Parallel Inlet report for %s:\n' % self.label
159            message += '--------------------------------------------\n'
160            message += 'Q [m^3/s]: %.2f\n' % self.Q
161       
162            print message
163
164
165    def set_logging(self, flag=True):
166        # WARNING: Must be called by master proc to have any effect
167
168        stats = self.statistics()
169        self.logging = flag
170       
171        if self.myid == self.master_proc:
172            # If flag is true open file with mode = "w" to form a clean file for logging
173            # PETE: Have to open separate file for each processor
174            if self.logging:
175                self.log_filename = self.label + '.log'
176                log_to_file(self.log_filename, stats, mode='w')
177                log_to_file(self.log_filename, 'time,Q')
178
179            #log_to_file(self.log_filename, self.culvert_type)
180
181
182    def timestepping_statistics(self):
183
184        message  = '%.5f, ' % self.domain.get_time()
185        message += '%.5f, ' % self.Q
186
187        return message
188
189    def log_timestepping_statistics(self):
190        # WARNING: Must be called by master proc to have any effect
191
192        if self.myid == self.master_proc:
193            if self.logging:
194                log_to_file(self.log_filename, self.timestepping_statistics())
195
196
197
198    def set_Q(self, Q):
199        # LOCAL
200        self.Q = Q
201
202    def get_Q(self):
203        # LOCAL
204        return self.Q
205
206
207    def get_inlet(self):
208        # LOCAL
209        return self.inlet
210
211    def get_line(self):
212        return self.line
213
214    def get_master_proc(self):
215        return self.master_proc
216
217    def __parallel_safe(self):
218        return True
Note: See TracBrowser for help on using the repository browser.