source: trunk/anuga_work/development/gareth/tests/util.py @ 8375

Last change on this file since 8375 was 8375, checked in by davies, 13 years ago

balanced_dev: fixed stack overflow problem, & new 'transect plot'
routine in util.py

File size: 8.1 KB
RevLine 
[8308]1""" Utilities for reading data / plotting of channel/floodplain case
2"""
3
4class get_output:
5    """Read in data from an .sww file in a convenient form
[8353]6       e.g.
7        p = util.get_output('channel3.sww', minimum_allowed_height=0.01)
8       
9       p then contains most relevant information as e.g., p.stage, p.elev, p.xmom, etc
[8308]10    """
[8353]11    def __init__(self, filename, minimum_allowed_height=1.0e-03):
[8308]12        self.x, self.y, self.time, self.vols, self.stage, \
13                self.elev, self.xmom, self.ymom, \
[8353]14                self.xvel, self.yvel, self.vel, self.minimum_allowed_height = \
15                read_output(filename, minimum_allowed_height)
[8308]16
17
[8353]18def read_output(filename, minimum_allowed_height):
[8308]19    # Input: The name of an .sww file to read data from,
20    #                    e.g. read_sww('channel3.sww')
21    #
22    # Purpose: To read the sww file, and output a number of variables as arrays that
23    #          we can then manipulate (e.g. plot, interrogate)
24    #
25    # Output: x, y, time, stage, elev, xmom, ymom, xvel, yvel, vel
26
27    # Import modules
28
29    from Scientific.IO.NetCDF import NetCDFFile
30
31
32    # Open ncdf connection
33    fid=NetCDFFile(filename)
34
35
36    # Read variables
37    x=fid.variables['x']
38    x=x.getValue()
39    y=fid.variables['y']
40    y=y.getValue()
41
42    stage=fid.variables['stage']
43    stage=stage.getValue()
44
45    elev=fid.variables['elevation']
46    elev=elev.getValue()
47
48    xmom=fid.variables['xmomentum']
49    xmom=xmom.getValue()
50
51    ymom=fid.variables['ymomentum']
52    ymom=ymom.getValue()
53
54    time=fid.variables['time']
55    time=time.getValue()
56
57    vols=fid.variables['volumes']
58    vols=vols.getValue()
59
60
61    # Calculate velocity = momentum/depth
62    xvel=xmom*0.0
63    yvel=ymom*0.0
64
65    for i in range(xmom.shape[0]):
[8353]66        xvel[i,:]=xmom[i,:]/(stage[i,:]-elev+1.0e-06)*(stage[i,:]> elev+minimum_allowed_height)
67        yvel[i,:]=ymom[i,:]/(stage[i,:]-elev+1.0e-06)*(stage[i,:]> elev+minimum_allowed_height)
[8308]68
69    vel = (xvel**2+yvel**2)**0.5
70
[8353]71    return x, y, time, vols, stage, elev, xmom, ymom, xvel, yvel, vel, minimum_allowed_height
[8308]72
73##############
74
75
76
77class get_centroids:
78    """
[8353]79    Extract centroid values from the output of get_output. 
80    e.g.
81        p = util.get_output('my_sww.sww', minimum_allowed_height=0.01) # vertex values
82        pc=util.get_centroids(p, velocity_extrapolation=True) # centroid values
[8308]83    """
[8353]84    def __init__(self,p, velocity_extrapolation=False):
85        self.time, self.x, self.y, self.stage, self.xmom,\
[8308]86             self.ymom, self.elev, self.xvel, \
[8353]87             self.yvel, self.vel= \
88             get_centroid_values(p, velocity_extrapolation)
89                                 
[8308]90
[8353]91def get_centroid_values(p, velocity_extrapolation):
[8308]92    # Input: p is the result of e.g. p=util.get_output('mysww.sww'). See the get_output class defined above
93    # Output: Values of x, y, Stage, xmom, ymom, elev, xvel, yvel, vel at centroids
94    import numpy
95   
96    # Make 3 arrays, each containing one index of a vertex of every triangle.
97    l=len(p.vols)
98    vols0=numpy.zeros(l, dtype='int')
99    vols1=numpy.zeros(l, dtype='int')
100    vols2=numpy.zeros(l, dtype='int')
101
[8353]102    # FIXME: 22/2/12/ - I think this loop is slow, should be able to do this
103    # another way
[8308]104    for i in range(l):
105        vols0[i]=p.vols[i][0]
106        vols1[i]=p.vols[i][1]
107        vols2[i]=p.vols[i][2]
108
109    # Then use these to compute centroid averages
110    x_cent=(p.x[vols0]+p.x[vols1]+p.x[vols2])/3.0
111    y_cent=(p.y[vols0]+p.y[vols1]+p.y[vols2])/3.0
112
113    stage_cent=(p.stage[:,vols0]+p.stage[:,vols1]+p.stage[:,vols2])/3.0
114    elev_cent=(p.elev[vols0]+p.elev[vols1]+p.elev[vols2])/3.0
115
[8353]116    # Here, we need to treat differently the case of momentum extrapolation or
117    # velocity extrapolation
118    if velocity_extrapolation:
119        xvel_cent=(p.xvel[:,vols0]+p.xvel[:,vols1]+p.xvel[:,vols2])/3.0
120        yvel_cent=(p.yvel[:,vols0]+p.yvel[:,vols1]+p.yvel[:,vols2])/3.0
121       
122        # Now compute momenta
123        xmom_cent=stage_cent*0.0
124        ymom_cent=stage_cent*0.0
[8308]125
[8353]126        t=len(p.time)
[8308]127
[8353]128        for i in range(t):
129            xmom_cent[i,:]=xvel_cent[i,:]*(stage_cent[i,:]-elev_cent+1.0e-06)*\
130                                            (stage_cent[i,:]>elev_cent+p.minimum_allowed_height)
131            ymom_cent[i,:]=yvel_cent[i,:]*(stage_cent[i,:]-elev_cent+1.0e-06)*\
132                                            (stage_cent[i,:]>elev_cent+p.minimum_allowed_height)
133
134    else:
135        xmom_cent=(p.xmom[:,vols0]+p.xmom[:,vols1]+p.xmom[:,vols2])/3.0
136        ymom_cent=(p.ymom[:,vols0]+p.ymom[:,vols1]+p.ymom[:,vols2])/3.0
137
138        # Now compute velocities
139        xvel_cent=stage_cent*0.0
140        yvel_cent=stage_cent*0.0
141
142        t=len(p.time)
143
144        for i in range(t):
145            xvel_cent[i,:]=xmom_cent[i,:]/(stage_cent[i,:]-elev_cent+1.0e-06)*(stage_cent[i,:]>elev_cent+p.minimum_allowed_height)
146            yvel_cent[i,:]=ymom_cent[i,:]/(stage_cent[i,:]-elev_cent+1.0e-06)*(stage_cent[i,:]>elev_cent+p.minimum_allowed_height)
147   
148
149    # Compute velocity
[8308]150    vel_cent=(xvel_cent**2 + yvel_cent**2)**0.5
151
[8353]152    return p.time, x_cent, y_cent, stage_cent, xmom_cent,\
[8308]153             ymom_cent, elev_cent, xvel_cent, yvel_cent, vel_cent
154
155# Make plot of stage over time.
156#pylab.close()
157#pylab.ion()
158#pylab.plot(time, stage[:,1])
159#for i in range(201):
160#    pylab.plot(time,stage[:,i])
161
162# Momentum should be 0.
163#print 'Momentum max/min is', xmom.max() , xmom.min()
164
165#pylab.gca().set_aspect('equal')
166#pylab.scatter(x,y,c=elev,edgecolors='none')
167#pylab.colorbar()
168#
169#n=xvel.shape[0]-1
170#pylab.quiver(x,y,xvel[n,:],yvel[n,:])
171#pylab.savefig('Plot1.png')
[8375]172
173def animate_1D(time, var, x, ylab=' '): #, x=range(var.shape[1]), vmin=var.min(), vmax=var.max()):
174    # Input: time = one-dimensional time vector;
175    #        var =  array with first dimension = len(time) ;
176    #        x = (optional) vector width dimension equal to var.shape[1];
177   
178    import pylab
179    import numpy
180   
181   
182
183    pylab.close()
184    pylab.ion()
185
186    # Initial plot
187    vmin=var.min()
188    vmax=var.max()
189    line, = pylab.plot( (x.min(), x.max()), (vmin, vmax), 'o')
190
191    # Lots of plots
192    for i in range(len(time)):
193        line.set_xdata(x)
194        line.set_ydata(var[i,:])
195        pylab.draw()
196        pylab.xlabel('x')
197        pylab.ylabel(ylab)
198        pylab.title('time = ' + str(time[i]))
199   
200    return
201
202def near_transect(p, point1, point2, tol=1.):
203    # Function to get the indices of points in p less than 'tol' from the line
204    # joining (x1,y1), and (x2,y2)
205    # p comes from util.get_output('mysww.sww')
206    #
207    # e.g.
208    # import util
209    # #import transect_interpolate
210    # from matplotlib import pyplot
211    # p=util.get_output('merewether_1m.sww',0.01)
212    # p2=util.get_centroids(p,velocity_extrapolation=True)
213    # #xxx=transect_interpolate.near_transect(p,[95., 85.], [120.,68.],tol=2.)
214    # xxx=util.near_transect(p,[95., 85.], [120.,68.],tol=2.)
215    # pyplot.scatter(xxx[1],p.vel[140,xxx[0]],color='red')
216
217    x1=point1[0]
218    y1=point1[1]
219
220    x2=point2[0]
221    y2=point2[1]
222
223    # Find line equation a*x + b*y + c = 0
224    # based on y=gradient*x +intercept
225    if x1!=x2:
226        gradient= (y2-y1)/(x2-x1)
227        intercept = y1 - gradient*x1
228
229        a = -gradient
230        b = 1.
231        c = -intercept
232    else:
233        #print 'FIXME: Still need to treat 0 and infinite gradients'
234        #assert 0==1
235        a=1.
236        b=0.
237        c=-x2
238
239    # Distance formula
240    inv_denom = 1./(a**2 + b**2)**0.5
241    distp = abs(p.x*a + p.y*b + c)*inv_denom
242
243    near_points = (distp<tol).nonzero()[0]
244   
245    # Now find a 'local' coordinate for the point, projected onto the line
246    # g1 = unit vector parallel to the line
247    # g2 = vector joining (x1,y1) and (p.x,p.y)
248    g1x = x2-x1
249    g1y = y2-y1
250    g1_norm = (g1x**2 + g1y**2)**0.5
251    g1x=g1x/g1_norm
252    g1y=g1x/g1_norm
253
254    g2x = p.x[near_points] - x1
255    g2y = p.y[near_points] - y1
256   
257    # Dot product = projected distance == a local coordinate
258    local_coord = g1x*g2x + g1y*g2y
259
260    return near_points, local_coord
Note: See TracBrowser for help on using the repository browser.