source: inundation/ga/storm_surge/parallel/advection.py @ 1407

Last change on this file since 1407 was 1407, checked in by steve, 20 years ago

Adding parallel update_timestep

File size: 6.1 KB
Line 
1import sys
2from os import sep
3sys.path.append('..'+sep+'pyvolution')
4
5"""Class Domain -
62D triangular domains for finite-volume computations of
7the advection equation.
8
9This module contains a specialisation of class Domain from module domain.py
10consisting of methods specific to the advection equantion
11
12The equation is
13
14  u_t + (v_1 u)_x + (v_2 u)_y = 0
15
16There is only one conserved quantity, the stage u
17
18The advection equation is a very simple specialisation of the generic
19domain and may serve as an instructive example or a test of other
20components such as visualisation.
21
22Ole Nielsen, Stephen Roberts, Duncan Gray, Christopher Zoppou
23Geoscience Australia, 2004
24"""
25
26from realtime_visualisation_new import Visualiser
27from domain import *
28Generic_domain = Domain #Rename
29
30class Domain(Generic_domain):
31
32    def __init__(self, coordinates, vertices, boundary = None, velocity = None):
33
34
35        Generic_domain.__init__(self, coordinates, vertices, boundary,
36                                ['stage'])
37
38        if velocity is None:
39            self.velocity = [1,0]
40        else:
41            self.velocity = velocity
42
43        #Only first is implemented for advection
44        self.default_order = self.order = 1
45
46        #Realtime visualisation
47        self.visualise = False
48        self.visualise_color_stage = False
49        self.visualise_timer = True
50        self.visualise_range_z = None
51
52        self.smooth = True
53
54
55
56    def initialise_visualiser(self,scale_z=1.0):
57        #Realtime visualisation
58        self.visualiser = Visualiser(self,scale_z)
59        self.visualise = True
60
61
62    def check_integrity(self):
63        Generic_domain.check_integrity(self)
64
65        msg = 'Conserved quantity must be "stage"'
66        assert self.conserved_quantities[0] == 'stage', msg
67
68
69    def flux_function(self, normal, ql, qr, zl=None, zr=None):
70        """Compute outward flux as inner product between velocity
71        vector v=(v_1, v_2) and normal vector n.
72
73        if <n,v> > 0 flux direction is outward bound and its magnitude is
74        determined by the quantity inside volume: ql.
75        Otherwise it is inbound and magnitude is determined by the
76        quantity outside the volume: qr.
77        """
78
79        v1 = self.velocity[0]
80        v2 = self.velocity[1]
81
82
83        normal_velocity = v1*normal[0] + v2*normal[1]
84
85        if normal_velocity < 0:
86            flux = qr * normal_velocity
87        else:
88            flux = ql * normal_velocity
89
90        max_speed = abs(normal_velocity)
91        return flux, max_speed
92
93
94    def compute_fluxes(self):
95        """Compute all fluxes and the timestep suitable for all volumes
96        in domain.
97
98        Compute total flux for each conserved quantity using "flux_function"
99
100        Fluxes across each edge are scaled by edgelengths and summed up
101        Resulting flux is then scaled by area and stored in
102        domain.explicit_update
103
104        The maximal allowable speed computed by the flux_function
105        for each volume
106        is converted to a timestep that must not be exceeded. The minimum of
107        those is computed as the next overall timestep.
108
109        Post conditions:
110        domain.explicit_update is reset to computed flux values
111        domain.timestep is set to the largest step satisfying all volumes.
112        """
113
114        import sys
115        from Numeric import zeros, Float
116        from config import max_timestep
117
118        N = self.number_of_elements
119
120        neighbours = self.neighbours
121        neighbour_edges = self.neighbour_edges
122        normals = self.normals
123
124        areas = self.areas
125        radii = self.radii
126        edgelengths = self.edgelengths
127
128        timestep = max_timestep #FIXME: Get rid of this
129
130        #Shortcuts
131        Stage = self.quantities['stage']
132
133        #Arrays
134        stage = Stage.edge_values
135
136        stage_bdry = Stage.boundary_values
137
138        flux = zeros(1, Float) #Work array for summing up fluxes
139
140        #Loop
141        for k in range(N):
142            optimal_timestep = float(sys.maxint)
143
144            flux[:] = 0.  #Reset work array
145            for i in range(3):
146                #Quantities inside volume facing neighbour i
147                ql = stage[k, i]
148
149                #Quantities at neighbour on nearest face
150                n = neighbours[k,i]
151                if n < 0:
152                    m = -n-1 #Convert neg flag to index
153                    qr = stage_bdry[m]
154                else:
155                    m = neighbour_edges[k,i]
156                    qr = stage[n, m]
157
158
159                #Outward pointing normal vector
160                normal = normals[k, 2*i:2*i+2]
161
162                #Flux computation using provided function
163                edgeflux, max_speed = self.flux_function(normal, ql, qr)
164                flux -= edgeflux * edgelengths[k,i]
165
166                #Update optimal_timestep
167                try:
168                    optimal_timestep = min(optimal_timestep, radii[k]/max_speed)
169                except ZeroDivisionError:
170                    pass
171
172            #Normalise by area and store for when all conserved
173            #quantities get updated
174            flux /= areas[k]
175            Stage.explicit_update[k] = flux[0]
176
177            timestep = min(timestep, optimal_timestep)
178
179        self.timestep = timestep
180
181
182
183    def evolve(self, yieldstep = None, finaltime = None):
184        """Specialisation of basic evolve method from parent class
185        """
186
187        #Initialise real time viz if requested
188        if self.visualise is True and self.time == 0.0:
189            import realtime_visualisation_new as visualise
190            self.visualiser.update_quantity('stage')
191            self.visualiser.update_timer()
192
193        #Call basic machinery from parent class
194        for t in Generic_domain.evolve(self, yieldstep, finaltime):
195            #Real time viz
196            if self.visualise is True:
197                self.visualiser.update_quantity('stage')
198                self.visualiser.update_timer()
199
200            #Pass control on to outer loop for more specific actions
201            yield(t)
Note: See TracBrowser for help on using the repository browser.