-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathcomputeQ.py
executable file
·206 lines (171 loc) · 6.19 KB
/
computeQ.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#!/usr/bin/env python3
#
#+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!
# #
# computeQ.py #
# #
#+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!
#
# Author: Pat Prodanovic, Ph.D., P.Eng.
#
# Date: Apr 5, 2018
#
# Purpose: Script takes in a *.slf file (2d for now), and computes the
# discharge through sections (which have to be re-sampled and be
# provided in PPUTILS line format). The cross sections have to be
# defined such that they are perpedicular to the flow. If the sections
# are not perpedicular to the flow, garbage results may be reported.
#
# Uses: Python 2 or 3, Numpy
#
# Example:
#
# python computeQ.py -i result.slf -l line.csv -o line_Q.csv
# where:
#
# -i ==> 2d *.slf result file, containing variables depth and velocity
# -l ==> PPUTILS formatted line fine, resampled (shapeid,x,y columns)
# -o ==> output *.csv file, which prints a time series of Q for each
# section in the -l file
#
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Global Imports
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import os,sys # system parameters
import numpy as np # numpy
import matplotlib.tri as mtri # matplotlib triangulations
from ppmodules.selafin_io_pp import * # to get SELAFIN I/O
from ppmodules.utilities import * # to get the utilities
from scipy.integrate import simps # simpson's rule integration
#
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# MAIN
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
curdir = os.getcwd()
#
# I/O
if len(sys.argv) != 7:
print('Wrong number of Arguments, stopping now...')
print('Usage:')
print('python computeQ.py -i result.slf -l line.csv -o line_Q.csv')
sys.exit()
input_file = sys.argv[2]
lines_file = sys.argv[4]
output_file = sys.argv[6]
# now read the input *.slf geometry file
slf = ppSELAFIN(input_file)
slf.readHeader()
slf.readTimes()
times = slf.getTimes()
vnames = slf.getVarNames()
vunits = slf.getVarUnits()
x = slf.getMeshX()
y = slf.getMeshY()
IKLE= slf.getIKLE()
NPOIN = len(x)
# determine if the *.slf file is 2d or 3d by reading how many planes it has
NPLAN = slf.getNPLAN()
if NPLAN > 1:
print('3d *.slf files not supported yet. Exiting!')
sys.exit(0)
# the number of time steps in the *.slf file
ntimes = len(times)
# use numpy to read the lines file in pputils format
lines_data = np.loadtxt(lines_file, delimiter=',',skiprows=0,unpack=True)
# boundary data
shapeid_lns = lines_data[0,:]
x_lns = lines_data[1,:]
y_lns = lines_data[2,:]
# round boundary nodes to three decimals
x_lns = np.around(x_lns,decimals=3)
y_lns = np.around(y_lns,decimals=3)
# need to compute chainage for each line
dist = np.zeros(len(shapeid_lns))
sta = np.zeros(len(shapeid_lns))
for i in range(1, len(shapeid_lns)):
if (shapeid_lns[i] - shapeid_lns[i-1] < 0.001):
xdist = x_lns[i] - x_lns[i-1]
ydist = y_lns[i] - y_lns[i-1]
dist[i] = np.sqrt(xdist*xdist + ydist*ydist)
sta[i] = sta[i-1] + dist[i]
# get the unique line ids
unique_lines = np.unique(shapeid_lns)
# find out how many different lines there are
n_lns = len(unique_lines)
# the IKLE array starts at element 1, but matplotlib needs it to start
# at zero
IKLE[:,:] = IKLE[:,:] - 1
# create triangulation object using matplotlib
triang = mtri.Triangulation(x, y, IKLE)
# now we need to find if the result file has these variables:
# DEPTH, VELOCITY U, VELOCITY V
# initialize the indexes to -1
depth_idx = -1
velu_idx = -1
velv_idx = -1
for i in range(len(vnames)):
if ((vnames[i].find('WATER DEPTH') > -1)):
depth_idx = i
if ((vnames[i].find('VELOCITY U') > -1)):
velu_idx = i
if ((vnames[i].find('VELOCITY V') > -1)):
velv_idx = i
if ((depth_idx < 0) or (velu_idx < 0) or (velv_idx < 0) ):
print('Required variables for computation not found.')
print('Please include WATER DEPTH, VELOCITY U and VELOCITY V')
print('in the *.slf input file and try again. Exiting!')
sys.exit(0)
# the final results variable where the results will be saved
Q = np.zeros( (len(times), n_lns) )
# this is the start of the main loop
for t in range(len(times)):
# print time step to the user
print('Computing Q at time step index :' + str(t))
# read the snapshot for time t from the *.slf file
slf.readVariables(t)
master_results = slf.getVarValues()
# store depths, velu and velv from the input file
depths = master_results[depth_idx, :]
velu = master_results[velu_idx, :]
velv = master_results[velv_idx, :]
# to perform the interpolations at the nodes of the resampled lines
# for depth, velu, and velv
interpolator_depths = mtri.LinearTriInterpolator(triang, depths)
depths_lns = interpolator_depths(x_lns, y_lns)
interpolator_velu = mtri.LinearTriInterpolator(triang, velu)
velu_lns = interpolator_velu(x_lns, y_lns)
interpolator_velv = mtri.LinearTriInterpolator(triang, velv)
velv_lns = interpolator_velv(x_lns, y_lns)
uh = velu_lns[:] * depths_lns[:]
vh = velv_lns[:] * depths_lns[:]
mag = np.sqrt( uh*uh + vh*vh)
# now go through each line, and integrate
for j in range(n_lns):
cursta = list()
curmag = list()
for i in range(len(mag)):
if (abs(unique_lines[j] - shapeid_lns[i]) < 0.01):
cursta.append(sta[i])
curmag.append(mag[i])
Q[t,j] = simps(curmag,cursta)
# prints the final result to the file
# write the header string
header_str = 'time, '
for i in range(n_lns-1):
header_str = header_str + str(unique_lines[i]) + ', '
header_str = header_str + str(unique_lines[n_lns-1]) + '\n'
print('Writing the output file ...')
# create the output file
fout = open(output_file, 'w')
# write the header string
fout.write(header_str)
# write the output file
for t in range(len(times)):
line = str(times[t]) + ', '
for j in range(n_lns-1):
line = line + str(Q[t,j]) + ', '
line = line + str(Q[t,n_lns-1])
line = line + '\n'
fout.write(line)
fout.close()
print('All done!')