source: inundation/ga/storm_surge/pyvolution/advection.py @ 1507

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

Changes to visualisation. Can use visualise_color_stage to color stage, but it uses python update (slow).

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