goPEST 0.0.11__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- goPEST-0.0.11.dist-info/LICENSE +11 -0
- goPEST-0.0.11.dist-info/METADATA +95 -0
- goPEST-0.0.11.dist-info/RECORD +30 -0
- goPEST-0.0.11.dist-info/WHEEL +5 -0
- goPEST-0.0.11.dist-info/entry_points.txt +2 -0
- goPEST-0.0.11.dist-info/top_level.txt +1 -0
- gopest/__init__.py +11 -0
- gopest/_version.py +16 -0
- gopest/check_slaves.py +402 -0
- gopest/commands.py +80 -0
- gopest/common.py +194 -0
- gopest/data/case.pst +67 -0
- gopest/data/goPESTconfig.aut2.toml +95 -0
- gopest/data/goPESTconfig.toml +94 -0
- gopest/data/goPESTobs.list +793 -0
- gopest/data/goPESTpar.list +95 -0
- gopest/make_case_pst.py +229 -0
- gopest/obs.py +297 -0
- gopest/obs_def.py +2086 -0
- gopest/par.py +332 -0
- gopest/par_def.py +313 -0
- gopest/pest_model.py +245 -0
- gopest/rename_latest_files.py +35 -0
- gopest/run_beopest.py +205 -0
- gopest/run_ns_pr.py +617 -0
- gopest/submit_beopest.py +931 -0
- gopest/utils/__init__.py +0 -0
- gopest/utils/gener_groups.py +192 -0
- gopest/utils/t2listingh5.py +376 -0
- gopest/utils/waiwera_listing.py +587 -0
gopest/utils/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
from mulgrids import *
|
|
2
|
+
from t2data import *
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def normalname_match(name_wc, name):
|
|
7
|
+
""" return true if the name_wc (wild cast * supported) match name """
|
|
8
|
+
is_match = True
|
|
9
|
+
for i in xrange(5):
|
|
10
|
+
if name_wc[i] != '*':
|
|
11
|
+
if name_wc[i] != name[i]:
|
|
12
|
+
is_match = False
|
|
13
|
+
break
|
|
14
|
+
return is_match
|
|
15
|
+
|
|
16
|
+
def toughname_match(name_wc, name):
|
|
17
|
+
""" return true if the name_wc (wild cast * supported) match name """
|
|
18
|
+
from mulgrids import unfix_blockname
|
|
19
|
+
c_name_wc = unfix_blockname(name_wc)
|
|
20
|
+
c_name = unfix_blockname(name)
|
|
21
|
+
|
|
22
|
+
is_match = True
|
|
23
|
+
for i in xrange(5):
|
|
24
|
+
if c_name_wc[i] != '*':
|
|
25
|
+
if c_name_wc[i] != c_name[i]:
|
|
26
|
+
is_match = False
|
|
27
|
+
break
|
|
28
|
+
return is_match
|
|
29
|
+
|
|
30
|
+
# GENER purpose check
|
|
31
|
+
|
|
32
|
+
def is_upflow(gener,geo,convention='*** 1'):
|
|
33
|
+
b = gener.block
|
|
34
|
+
w = gener.name
|
|
35
|
+
checks = [
|
|
36
|
+
normalname_match(convention,w),
|
|
37
|
+
geo.layer[geo.layer_name(b)].name == geo.layerlist[-1].name,
|
|
38
|
+
gener.type == 'MASS'
|
|
39
|
+
]
|
|
40
|
+
return all(checks)
|
|
41
|
+
|
|
42
|
+
def is_heat(gener,geo,convention='*** 2'):
|
|
43
|
+
b = gener.block
|
|
44
|
+
w = gener.name
|
|
45
|
+
checks = [
|
|
46
|
+
normalname_match(convention,w),
|
|
47
|
+
geo.layer[geo.layer_name(b)].name == geo.layerlist[-1].name,
|
|
48
|
+
gener.type == 'HEAT'
|
|
49
|
+
]
|
|
50
|
+
return all(checks)
|
|
51
|
+
|
|
52
|
+
def is_upflow_rech(gener,geo,convention='*** 3'):
|
|
53
|
+
b = gener.block
|
|
54
|
+
w = gener.name
|
|
55
|
+
checks = [
|
|
56
|
+
normalname_match(convention,w),
|
|
57
|
+
geo.layer[geo.layer_name(b)].name == geo.layerlist[-1].name,
|
|
58
|
+
gener.type == 'RECH'
|
|
59
|
+
]
|
|
60
|
+
return all(checks)
|
|
61
|
+
|
|
62
|
+
def is_side_rech(gener,geo,convention='*****'):
|
|
63
|
+
b = gener.block
|
|
64
|
+
w = gener.name
|
|
65
|
+
checks = [
|
|
66
|
+
normalname_match(convention,w),
|
|
67
|
+
b == w,
|
|
68
|
+
gener.type == 'RECH'
|
|
69
|
+
]
|
|
70
|
+
return all(checks)
|
|
71
|
+
|
|
72
|
+
def is_rain(gener,geo,convention='*****'):
|
|
73
|
+
b = gener.block
|
|
74
|
+
w = gener.name
|
|
75
|
+
checks = [
|
|
76
|
+
normalname_match(convention,w),
|
|
77
|
+
geo.layer_name(b) == geo.layerlist[geo.num_layers - geo.column[geo.column_name(b)].num_layers].name,
|
|
78
|
+
gener.type == 'MASS'
|
|
79
|
+
]
|
|
80
|
+
return all(checks)
|
|
81
|
+
|
|
82
|
+
def is_spring(gener,geo,convention='SP***'):
|
|
83
|
+
b = gener.block
|
|
84
|
+
w = gener.name
|
|
85
|
+
checks = [
|
|
86
|
+
normalname_match(convention,w),
|
|
87
|
+
gener.type in ['DELG','MASS'],
|
|
88
|
+
]
|
|
89
|
+
return all(checks)
|
|
90
|
+
|
|
91
|
+
def check_geners(geners, checks):
|
|
92
|
+
""" geners, a list of t2generators. checks, a list of functions that
|
|
93
|
+
accepts generator as argument and return True/False, names of functions
|
|
94
|
+
will be used as dict key when returning counts of each function when
|
|
95
|
+
returning True. A list of partial functions can be in place the list of
|
|
96
|
+
functions. """
|
|
97
|
+
|
|
98
|
+
try:
|
|
99
|
+
fnames = [f.__name__ for f in checks]
|
|
100
|
+
except AttributeError:
|
|
101
|
+
fnames = [pf.func.__name__ for pf in checks]
|
|
102
|
+
|
|
103
|
+
# set all counter to zero, dict with func names as key
|
|
104
|
+
count = dict([(n,0) for n in fnames])
|
|
105
|
+
count['UNKNOWN'] = 0
|
|
106
|
+
|
|
107
|
+
for i,g in enumerate(geners):
|
|
108
|
+
match = []
|
|
109
|
+
for f,t in zip(checks,fnames):
|
|
110
|
+
if f(g):
|
|
111
|
+
count[t] += 1
|
|
112
|
+
match.append(t)
|
|
113
|
+
if len(match) > 1:
|
|
114
|
+
print('WARNING: %s match types: %s' % (g.name,','.join(match)))
|
|
115
|
+
if len(match) == 0:
|
|
116
|
+
count['UNKNOWN'] += 1
|
|
117
|
+
print('WARNING: %s doe not match any type.' % g.name)
|
|
118
|
+
|
|
119
|
+
return count
|
|
120
|
+
|
|
121
|
+
def wai_area_polygon():
|
|
122
|
+
pline = [
|
|
123
|
+
np.array([ 2768202.24117734 , 6270490.54421648]),
|
|
124
|
+
np.array([ 2776545.06074986 , 6276563.022725 ]),
|
|
125
|
+
np.array([ 2777310.95894013 , 6277137.4463677 ]),
|
|
126
|
+
np.array([ 2778049.5036236 , 6277766.57702399]),
|
|
127
|
+
np.array([ 2780784.85430311 , 6280173.68562197]),
|
|
128
|
+
np.array([ 2781988.4086021 , 6281377.23992095]),
|
|
129
|
+
np.array([ 2783629.61900981 , 6294807.81175738]),
|
|
130
|
+
np.array([ 2772524.09525097 , 6296312.25463111]),
|
|
131
|
+
np.array([ 2764454.8107464 , 6291662.15847593]),
|
|
132
|
+
np.array([ 2762567.41877753 , 6281213.11888018]),
|
|
133
|
+
np.array([ 2764865.11334833 , 6272842.94580086]),
|
|
134
|
+
np.array([ 2767436.34298707 , 6270955.553832 ])]
|
|
135
|
+
return pline
|
|
136
|
+
|
|
137
|
+
def ro_area_polygon():
|
|
138
|
+
pline = [
|
|
139
|
+
np.array([ 2783739.03303699 , 6294671.0442234 ]),
|
|
140
|
+
np.array([ 2781742.22704094 , 6281623.42148211]),
|
|
141
|
+
np.array([ 2785216.12240393 , 6279462.49444529]),
|
|
142
|
+
np.array([ 2787267.63541357 , 6279626.61548606]),
|
|
143
|
+
np.array([ 2788416.48269896 , 6279134.25236375]),
|
|
144
|
+
np.array([ 2795911.34356084 , 6279927.50406081]),
|
|
145
|
+
np.array([ 2790440.64220181 , 6292263.93562543]),
|
|
146
|
+
np.array([ 2784586.99174764 , 6294534.27668943])]
|
|
147
|
+
return pline
|
|
148
|
+
|
|
149
|
+
def th_area_polygon():
|
|
150
|
+
pline = [
|
|
151
|
+
np.array([ 2788334.42217858 , 6279298.37340452]),
|
|
152
|
+
np.array([ 2795938.69706763 , 6280118.97860838]),
|
|
153
|
+
np.array([ 2797579.90747534 , 6272131.75462419]),
|
|
154
|
+
np.array([ 2794188.07263274 , 6265129.25688463]),
|
|
155
|
+
np.array([ 2789784.15803872 , 6262776.85530024]),
|
|
156
|
+
np.array([ 2778842.75532066 , 6260479.16072945]),
|
|
157
|
+
np.array([ 2771566.72251314 , 6264992.48935065]),
|
|
158
|
+
np.array([ 2768421.0692317 , 6269970.82758737]),
|
|
159
|
+
np.array([ 2778131.56414398 , 6277848.63754438]),
|
|
160
|
+
np.array([ 2781632.81301376 , 6280966.93731903]),
|
|
161
|
+
np.array([ 2784942.58733598 , 6279407.7874317 ]),
|
|
162
|
+
np.array([ 2786747.91878446 , 6279653.96899286]),
|
|
163
|
+
np.array([ 2788115.59412422 , 6279353.08041811])]
|
|
164
|
+
return pline
|
|
165
|
+
|
|
166
|
+
if __name__ == '__main__':
|
|
167
|
+
|
|
168
|
+
geo = mulgrid('gwai41458_09.dat')
|
|
169
|
+
nsdat = t2data('wai41458ns_464.dat')
|
|
170
|
+
prdat = t2data('wai41458pr_464.dat')
|
|
171
|
+
|
|
172
|
+
# check these possibilities
|
|
173
|
+
from functools import partial
|
|
174
|
+
g_types = [
|
|
175
|
+
partial(is_rain,geo=geo,convention='*** 0'),
|
|
176
|
+
partial(is_heat,geo=geo,convention='*** 2'),
|
|
177
|
+
partial(is_upflow,geo=geo,convention='*** 1'),
|
|
178
|
+
partial(is_upflow_rech,geo=geo,convention='*** 3'),
|
|
179
|
+
partial(is_side_rech,geo=geo,convention='*****')
|
|
180
|
+
]
|
|
181
|
+
|
|
182
|
+
print('+++++', nsdat.filename)
|
|
183
|
+
count = check_geners(nsdat.generatorlist, g_types)
|
|
184
|
+
for t in sorted(count.keys()):
|
|
185
|
+
print('%20s = %i' % (t,count[t]))
|
|
186
|
+
print('Total # of generators is ', len(nsdat.generatorlist))
|
|
187
|
+
|
|
188
|
+
print('+++++', prdat.filename)
|
|
189
|
+
count = check_geners(prdat.generatorlist, g_types)
|
|
190
|
+
for t in sorted(count.keys()):
|
|
191
|
+
print('%20s = %i' % (t,count[t]))
|
|
192
|
+
print('Total # of generators is ', len(prdat.generatorlist))
|
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright 2013, 2014 University of Auckland.
|
|
3
|
+
|
|
4
|
+
This file is part of TIM (Tim Isn't Mulgraph).
|
|
5
|
+
|
|
6
|
+
TIM is free software: you can redistribute it and/or modify
|
|
7
|
+
it under the terms of the GNU General Public License as published by
|
|
8
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
9
|
+
(at your option) any later version.
|
|
10
|
+
|
|
11
|
+
TIM is distributed in the hope that it will be useful,
|
|
12
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
GNU General Public License for more details.
|
|
15
|
+
|
|
16
|
+
You should have received a copy of the GNU General Public License
|
|
17
|
+
along with TIM. If not, see <http://www.gnu.org/licenses/>.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
"""
|
|
21
|
+
Wrap AUTOUGH2's hdf5 output as t2listing
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
import h5py
|
|
25
|
+
import numpy as np
|
|
26
|
+
|
|
27
|
+
from t2listing import *
|
|
28
|
+
# from t2listing import listingtable
|
|
29
|
+
from mulgrids import fix_blockname, unfix_blockname
|
|
30
|
+
|
|
31
|
+
from pprint import pprint as pp
|
|
32
|
+
import unittest
|
|
33
|
+
|
|
34
|
+
class h5table(listingtable):
|
|
35
|
+
""" Class emulating the listingtable class in PyTOUGH.
|
|
36
|
+
|
|
37
|
+
Class for table in listing file, with values addressable by index (0-based)
|
|
38
|
+
or row name, and column name: e.g. table[i] returns the ith row (as a
|
|
39
|
+
dictionary), table[rowname] returns the row with the specified name, and
|
|
40
|
+
table[colname] returns the column with the specified name.
|
|
41
|
+
|
|
42
|
+
!!! IMPORTANT !!!
|
|
43
|
+
.index needs to be set whenever listing object changed time index
|
|
44
|
+
"""
|
|
45
|
+
def __init__(self, cols, rows, h5_table,
|
|
46
|
+
num_keys = 1, allow_reverse_keys = False,
|
|
47
|
+
index = 0):
|
|
48
|
+
""" The row_format parameter is a dictionary with three keys,
|
|
49
|
+
'key','index' and 'values'. These contain the positions, in each row of
|
|
50
|
+
the table, of the start of the keys, index and data fields. The
|
|
51
|
+
row_line parameter is a list containing, for each row of the table, the
|
|
52
|
+
number of lines before it in the listing file, from the start of the
|
|
53
|
+
table. This is needed for TOUGH2_MP listing files, in which the rows
|
|
54
|
+
are not in index order and can also be duplicated.
|
|
55
|
+
|
|
56
|
+
h5_table should be the table within the h5 file.
|
|
57
|
+
"""
|
|
58
|
+
self.column_name = cols
|
|
59
|
+
self.row_name = rows
|
|
60
|
+
self.num_keys = num_keys
|
|
61
|
+
self.allow_reverse_keys = allow_reverse_keys
|
|
62
|
+
self._col = dict([(c,i) for i,c in enumerate(cols)])
|
|
63
|
+
self._row = dict([(r,i) for i,r in enumerate(rows)])
|
|
64
|
+
self._h5_table = h5_table
|
|
65
|
+
self._index = index # time index
|
|
66
|
+
|
|
67
|
+
def __repr__(self):
|
|
68
|
+
# h5 table lst._h5['element'][time index, eleme index, field index]
|
|
69
|
+
return repr(self.column_name) + '\n' + repr(self._h5_table[self._index, :, :])
|
|
70
|
+
|
|
71
|
+
def __getitem__(self, key):
|
|
72
|
+
if isinstance(key, int):
|
|
73
|
+
return dict(zip(['key'] + self.column_name, [self.row_name[key]] +
|
|
74
|
+
list(self._h5_table[self._index, key, :])))
|
|
75
|
+
else:
|
|
76
|
+
if key in self.column_name:
|
|
77
|
+
return self._h5_table[self._index, :, self._col[key]]
|
|
78
|
+
elif key in self.row_name:
|
|
79
|
+
rowindex = self._row[key]
|
|
80
|
+
return dict(zip(['key'] + self.column_name,
|
|
81
|
+
[self.row_name[rowindex]] +
|
|
82
|
+
list(self._h5_table[self._index, rowindex, :])))
|
|
83
|
+
elif len(key) > 1 and self.allow_reverse_keys:
|
|
84
|
+
revkey = key[::-1] # try reversed key for multi-key tables
|
|
85
|
+
if revkey in self.row_name:
|
|
86
|
+
rowindex = self._row[revkey]
|
|
87
|
+
return dict(zip(['key'] + self.column_name,
|
|
88
|
+
[self.row_name[rowindex][::-1]] +
|
|
89
|
+
list(-self._h5_table[self._index, rowindex, :])))
|
|
90
|
+
else: return None
|
|
91
|
+
|
|
92
|
+
def __add__(self, other):
|
|
93
|
+
raise NotImplementedError
|
|
94
|
+
"""Adds two listing tables together."""
|
|
95
|
+
if self.column_name == other.column_name and self.row_name == other.row_name:
|
|
96
|
+
from copy import copy
|
|
97
|
+
result = listingtable(copy(self.column_name), copy(self.row_name), num_keys = self.num_keys,
|
|
98
|
+
allow_reverse_keys = self.allow_reverse_keys)
|
|
99
|
+
result._data = self._data + other._data
|
|
100
|
+
return result
|
|
101
|
+
else: raise Exception("Incompatible tables: can't be added together.")
|
|
102
|
+
|
|
103
|
+
def __sub__(self, other):
|
|
104
|
+
raise NotImplementedError
|
|
105
|
+
"""Subtracts one listing table from another."""
|
|
106
|
+
if self.column_name == other.column_name and self.row_name == other.row_name:
|
|
107
|
+
from copy import copy
|
|
108
|
+
result = listingtable(copy(self.column_name), copy(self.row_name), num_keys = self.num_keys,
|
|
109
|
+
allow_reverse_keys = self.allow_reverse_keys)
|
|
110
|
+
result._data = self._data - other._data
|
|
111
|
+
return result
|
|
112
|
+
else: raise Exception("Incompatible tables: can't be subtracted.")
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class t2listingh5(object):
|
|
116
|
+
def __init__(self, filename):
|
|
117
|
+
"""
|
|
118
|
+
"""
|
|
119
|
+
self._table = {}
|
|
120
|
+
self._h5 = h5py.File(filename, 'r')
|
|
121
|
+
self.filename = filename
|
|
122
|
+
self.setup()
|
|
123
|
+
self.simulator = 'AUTOUGH2_H5'
|
|
124
|
+
|
|
125
|
+
def close(self):
|
|
126
|
+
self._h5.close()
|
|
127
|
+
|
|
128
|
+
def setup(self):
|
|
129
|
+
self.fulltimes = self._h5['fulltimes']['TIME']
|
|
130
|
+
self.num_fulltimes = len(self.fulltimes)
|
|
131
|
+
self._index = 0 # this is the internal one
|
|
132
|
+
### element table
|
|
133
|
+
if 'element' in self._h5:
|
|
134
|
+
cols = [x.decode('utf-8') for x in self._h5['element_fields']]
|
|
135
|
+
blocks = [fix_blockname(x.decode('utf-8')) for x in self._h5['element_names']]
|
|
136
|
+
table = h5table(cols, blocks, self._h5['element'], num_keys=1)
|
|
137
|
+
self._table['element'] = table
|
|
138
|
+
### connection table
|
|
139
|
+
if 'connection' in self._h5:
|
|
140
|
+
cols = [x.decode('utf-8') for x in self._h5['connection_fields'][:]]
|
|
141
|
+
b1 = [fix_blockname(x.decode('utf-8')) for x in self._h5['connection_names1'][:]]
|
|
142
|
+
b2 = [fix_blockname(x.decode('utf-8')) for x in self._h5['connection_names2'][:]]
|
|
143
|
+
table = h5table(cols, list(zip(b1,b2)), self._h5['connection'], num_keys=2,
|
|
144
|
+
allow_reverse_keys=True)
|
|
145
|
+
self._table['connection'] = table
|
|
146
|
+
### generation table
|
|
147
|
+
if 'generation' in self._h5:
|
|
148
|
+
cols = [x.decode('utf-8') for x in self._h5['generation_fields'][:]]
|
|
149
|
+
blocks = [fix_blockname(x.decode('utf-8')) for x in self._h5['generation_eleme'][:]]
|
|
150
|
+
geners = [fix_blockname(x.decode('utf-8')) for x in self._h5['generation_names'][:]]
|
|
151
|
+
table = h5table(cols, list(zip(blocks,geners)), self._h5['generation'], num_keys=1)
|
|
152
|
+
self._table['generation'] = table
|
|
153
|
+
# makes tables in self._table accessible as attributes
|
|
154
|
+
for key,table in self._table.items():
|
|
155
|
+
setattr(self, key, table)
|
|
156
|
+
# have to be get first table ready
|
|
157
|
+
self.index = 0
|
|
158
|
+
|
|
159
|
+
def history(self, selection, short=False, start_datetime=None):
|
|
160
|
+
"""
|
|
161
|
+
short is not used at the moment
|
|
162
|
+
"""
|
|
163
|
+
if isinstance(selection, tuple):
|
|
164
|
+
selection = [selection]
|
|
165
|
+
results = []
|
|
166
|
+
for tbl,b,cname in selection:
|
|
167
|
+
table_name, bi, fieldi = self.selection_index(tbl, b, cname)
|
|
168
|
+
if bi < 0:
|
|
169
|
+
bi = len(self.block_name_index) + bi
|
|
170
|
+
### important to convert cell index
|
|
171
|
+
ys = self._h5[table_name][:,bi,fieldi]
|
|
172
|
+
results.append((self.fulltimes, ys))
|
|
173
|
+
if len(results) == 1: results = results[0]
|
|
174
|
+
return results
|
|
175
|
+
|
|
176
|
+
def selection_index(self, tbl, b, field):
|
|
177
|
+
dname = {
|
|
178
|
+
'e': 'element',
|
|
179
|
+
'c': 'connection',
|
|
180
|
+
'g': 'generation',
|
|
181
|
+
}
|
|
182
|
+
def eleme_index(b):
|
|
183
|
+
if isinstance(b, str):
|
|
184
|
+
bi = self.block_name_index[b]
|
|
185
|
+
elif isinstance(b, int):
|
|
186
|
+
bi = b
|
|
187
|
+
else:
|
|
188
|
+
raise Exception('.history() block must be an int or str: %s (%s)' % (str(b),str(type(b))))
|
|
189
|
+
return bi
|
|
190
|
+
def conne_index(b):
|
|
191
|
+
if isinstance(b, tuple):
|
|
192
|
+
bi = self.connection_name_index[(str(b[0]), str(b[1]))]
|
|
193
|
+
elif isinstance(b, int):
|
|
194
|
+
bi = b
|
|
195
|
+
else:
|
|
196
|
+
raise Exception('.history() conne must be an int or (str,str): %s (%s)' % (str(b),str(type(b))))
|
|
197
|
+
return bi
|
|
198
|
+
def gener_index(b):
|
|
199
|
+
if isinstance(b, tuple):
|
|
200
|
+
bi = self.generation_name_index[(str(b[0]), str(b[1]))]
|
|
201
|
+
elif isinstance(b, int):
|
|
202
|
+
bi = b
|
|
203
|
+
else:
|
|
204
|
+
raise Exception('.history() gener must be an int or (str,str): %s (%s)' % (str(b),str(type(b))))
|
|
205
|
+
return bi
|
|
206
|
+
iname = {
|
|
207
|
+
'e': eleme_index,
|
|
208
|
+
'c': conne_index,
|
|
209
|
+
'g': gener_index,
|
|
210
|
+
}
|
|
211
|
+
if not hasattr(self, 'field_index'):
|
|
212
|
+
self.field_index = {}
|
|
213
|
+
for n,nn in dname.items():
|
|
214
|
+
for i,ff in enumerate(self._h5[nn + '_fields']):
|
|
215
|
+
self.field_index[(n,ff)] = i
|
|
216
|
+
return dname[tbl], iname[tbl](b), self.field_index[(tbl,field)]
|
|
217
|
+
|
|
218
|
+
@property
|
|
219
|
+
def block_name_index(self):
|
|
220
|
+
if not hasattr(self, '_block_name_index'):
|
|
221
|
+
self._block_name_index = {}
|
|
222
|
+
# self._block_name_index.update({str(e):i for i,e in enumerate(self._h5['element_names'])})
|
|
223
|
+
self._block_name_index.update({fix_blockname(str(e)):i for i,e in enumerate(self._h5['element_names'])})
|
|
224
|
+
return self._block_name_index
|
|
225
|
+
|
|
226
|
+
@property
|
|
227
|
+
def connection_name_index(self):
|
|
228
|
+
if not hasattr(self, '_connection_name_index'):
|
|
229
|
+
a = self._h5['connection_names1']
|
|
230
|
+
b = self._h5['connection_names2']
|
|
231
|
+
self._connection_name_index = {}
|
|
232
|
+
self._connection_name_index.update({(fix_blockname(str(x[0])),fix_blockname(str(x[1]))):i for i,x in enumerate(zip(a,b))})
|
|
233
|
+
return self._connection_name_index
|
|
234
|
+
|
|
235
|
+
@property
|
|
236
|
+
def generation_name_index(self):
|
|
237
|
+
if not hasattr(self, '_generation_name_index'):
|
|
238
|
+
a = self._h5['generation_eleme']
|
|
239
|
+
b = self._h5['generation_names']
|
|
240
|
+
self._generation_name_index = {}
|
|
241
|
+
# self._generation_name_index.update({(str(x[0]),str(x[1])):i for i,x in enumerate(zip(a,b))})
|
|
242
|
+
# self._generation_name_index.update({(fix_blockname(str(x[0])),(str(x[1]))):i for i,x in enumerate(zip(a,b))})
|
|
243
|
+
# self._generation_name_index.update({((str(x[0])),fix_blockname(str(x[1]))):i for i,x in enumerate(zip(a,b))})
|
|
244
|
+
self._generation_name_index.update({(fix_blockname(str(x[0])),fix_blockname(str(x[1]))):i for i,x in enumerate(zip(a,b))})
|
|
245
|
+
return self._generation_name_index
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def read_tables(self):
|
|
249
|
+
""" copy values from h5 into listingtables, with slicing """
|
|
250
|
+
if 'element' in self.table_names:
|
|
251
|
+
self.element._index = self.index
|
|
252
|
+
# for i,cname in enumerate(self.element.column_name):
|
|
253
|
+
# self.element._data[:,i] = self._h5['element'][self._index, :, i]
|
|
254
|
+
if 'connection' in self.table_names:
|
|
255
|
+
self.connection._index = self.index
|
|
256
|
+
# for i,cname in enumerate(self.connection.column_name):
|
|
257
|
+
# self.connection._data[:,i] = self._h5['connection'][self._index, :, i]
|
|
258
|
+
if 'generation' in self.table_names:
|
|
259
|
+
self.generation._index = self.index
|
|
260
|
+
# for i,cname in enumerate(self.generation.column_name):
|
|
261
|
+
# self.generation._data[:,i] = self._h5['generation'][self._index, :, i]
|
|
262
|
+
|
|
263
|
+
def get_index(self): return self._index
|
|
264
|
+
def set_index(self, i):
|
|
265
|
+
self._index = i
|
|
266
|
+
if self._index < 0: self._index += self.num_fulltimes
|
|
267
|
+
self.read_tables()
|
|
268
|
+
index = property(get_index, set_index)
|
|
269
|
+
|
|
270
|
+
def first(self): self.index = 0
|
|
271
|
+
def last(self): self.index = -1
|
|
272
|
+
def next(self):
|
|
273
|
+
"""Find and read next set of results; returns false if at end of listing"""
|
|
274
|
+
more = self.index < self.num_fulltimes - 1
|
|
275
|
+
if more: self.index += 1
|
|
276
|
+
return more
|
|
277
|
+
def prev(self):
|
|
278
|
+
"""Find and read previous set of results; returns false if at start of listing"""
|
|
279
|
+
more = self.index > 0
|
|
280
|
+
if more: self.index -= 1
|
|
281
|
+
return more
|
|
282
|
+
|
|
283
|
+
def get_table_names(self):
|
|
284
|
+
return sorted(self._table.keys())
|
|
285
|
+
table_names = property(get_table_names)
|
|
286
|
+
|
|
287
|
+
def get_time(self): return self.fulltimes[self.index]
|
|
288
|
+
def set_time(self, t):
|
|
289
|
+
if t < self.fulltimes[0]: self.index = 0
|
|
290
|
+
elif t > self.fulltimes[-1]: self.index = -1
|
|
291
|
+
else:
|
|
292
|
+
dt = np.abs(self.fulltimes - t)
|
|
293
|
+
self.index = np.argmin(dt)
|
|
294
|
+
time = property(get_time, set_time)
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
class test_fivespot(unittest.TestCase):
|
|
298
|
+
def setUp(self):
|
|
299
|
+
self.lst_h = t2listingh5('fivespot.h5')
|
|
300
|
+
self.lst_t= t2listing('expected.listing')
|
|
301
|
+
|
|
302
|
+
def test_match_tables(self):
|
|
303
|
+
# check row and column names
|
|
304
|
+
def check_names(tbl):
|
|
305
|
+
tbl_h = getattr(self.lst_h, tbl)
|
|
306
|
+
tbl_t = getattr(self.lst_t, tbl)
|
|
307
|
+
self.assertEqual(tbl_h.row_name, tbl_t.row_name)
|
|
308
|
+
for i,field in enumerate(tbl_h.column_name):
|
|
309
|
+
if tbl_t.column_name[i] in field:
|
|
310
|
+
match = True
|
|
311
|
+
else:
|
|
312
|
+
match = False
|
|
313
|
+
self.assertEqual(match, True, '%s: column name mismatch' % tbl)
|
|
314
|
+
for tbl in ['element', 'connection', 'generation']:
|
|
315
|
+
check_names(tbl)
|
|
316
|
+
# check table values, after change index also
|
|
317
|
+
def check_tables():
|
|
318
|
+
rtol = 1.0e-5 # roughly 4~5 significant digits from text listing file
|
|
319
|
+
for field in ['Temperature', 'Pressure', 'Vapour saturation']:
|
|
320
|
+
np.testing.assert_allclose(self.lst_h.element[field],
|
|
321
|
+
self.lst_t.element[field], rtol=rtol)
|
|
322
|
+
for field in ['Mass flow', 'Enthalpy', 'Heat flow']:
|
|
323
|
+
np.testing.assert_allclose(self.lst_h.connection[field],
|
|
324
|
+
self.lst_t.connection[field], rtol=rtol)
|
|
325
|
+
for field in ['Generation rate', 'Enthalpy']:
|
|
326
|
+
np.testing.assert_allclose(self.lst_h.generation[field],
|
|
327
|
+
self.lst_t.generation[field], rtol=rtol)
|
|
328
|
+
check_tables()
|
|
329
|
+
self.lst_h.last(); self.lst_t.last()
|
|
330
|
+
check_tables()
|
|
331
|
+
self.lst_h.first(); self.lst_t.first()
|
|
332
|
+
check_tables()
|
|
333
|
+
|
|
334
|
+
# check table with element index
|
|
335
|
+
def check_table_by_index(i):
|
|
336
|
+
tbl_h = self.lst_h.element[i]
|
|
337
|
+
tbl_t = self.lst_t.element[i]
|
|
338
|
+
for k in tbl_h.keys():
|
|
339
|
+
if k == 'key':
|
|
340
|
+
self.assertEqual(tbl_h[k], tbl_t[k])
|
|
341
|
+
else:
|
|
342
|
+
np.testing.assert_approx_equal(tbl_h[k], tbl_t[k], significant=5)
|
|
343
|
+
for i in range(len(self.lst_h.element.row_name)):
|
|
344
|
+
check_table_by_index(i)
|
|
345
|
+
|
|
346
|
+
# check table with element name
|
|
347
|
+
def check_table_by_name(b):
|
|
348
|
+
tbl_h = self.lst_h.element[b]
|
|
349
|
+
tbl_t = self.lst_t.element[b]
|
|
350
|
+
for k in tbl_h.keys():
|
|
351
|
+
if k == 'key':
|
|
352
|
+
self.assertEqual(tbl_h[k], tbl_t[k])
|
|
353
|
+
else:
|
|
354
|
+
np.testing.assert_approx_equal(tbl_h[k], tbl_t[k], significant=5)
|
|
355
|
+
for b in self.lst_h.element.row_name:
|
|
356
|
+
check_table_by_index(b)
|
|
357
|
+
|
|
358
|
+
def test_match_history(self):
|
|
359
|
+
self.assertEqual(self.lst_h.num_fulltimes, self.lst_t.num_fulltimes)
|
|
360
|
+
np.testing.assert_allclose(self.lst_h.fulltimes, self.lst_t.fulltimes)
|
|
361
|
+
rtol = 1.0e-5
|
|
362
|
+
# seems allfield names are identical with fivespot's EOS
|
|
363
|
+
for sel in [('e', 'AA106', 'Pressure'),
|
|
364
|
+
('e', 'AA 66', 'Temperature'),
|
|
365
|
+
('c', ('AA 66', 'AA 67'), 'Mass flow'),
|
|
366
|
+
('g', ('AA 11', 'PRO 1'), 'Generation rate'),
|
|
367
|
+
('g', ('AA 11', 'PRO 1'), 'Enthalpy'),
|
|
368
|
+
]:
|
|
369
|
+
xs_h, ys_h = self.lst_h.history(sel)
|
|
370
|
+
xs_t, ys_t = self.lst_t.history(sel)
|
|
371
|
+
np.testing.assert_allclose(xs_h, xs_t, rtol=rtol)
|
|
372
|
+
np.testing.assert_allclose(ys_h, ys_t, rtol=rtol)
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
if __name__ == '__main__':
|
|
376
|
+
unittest.main(verbosity=2)
|