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
|
@@ -0,0 +1,587 @@
|
|
|
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 Waiwera's hdf5 output as t2listing
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
import h5py
|
|
25
|
+
import numpy as np
|
|
26
|
+
|
|
27
|
+
from mulgrids import mulgrid
|
|
28
|
+
from t2listing import listingtable
|
|
29
|
+
|
|
30
|
+
import json
|
|
31
|
+
import time
|
|
32
|
+
import unittest
|
|
33
|
+
from pprint import pprint as pp
|
|
34
|
+
|
|
35
|
+
class wlisting(object):
|
|
36
|
+
def __init__(self, filename=None, geo=None, fjson=None, size_check=True):
|
|
37
|
+
""" Waiwera h5 output pretending to be t2listing
|
|
38
|
+
|
|
39
|
+
If corresponding geo is supplied, wlisting can behave more like
|
|
40
|
+
t2listing, which includes atmosphere blocks
|
|
41
|
+
|
|
42
|
+
If Waiwera input json is provided, then .generation has .row_name using
|
|
43
|
+
(t2 block name, source name) instead of (cell index, source index).
|
|
44
|
+
"""
|
|
45
|
+
self._table = {}
|
|
46
|
+
if isinstance(geo, str):
|
|
47
|
+
self.geo = mulgrid(geo)
|
|
48
|
+
else:
|
|
49
|
+
self.geo = geo
|
|
50
|
+
if self.geo is not None:
|
|
51
|
+
if self.geo.block_order != 'dmplex':
|
|
52
|
+
raise Exception("wlisting loading Waiwera output file requires a geometry with .block_order = 'dmplex'")
|
|
53
|
+
if isinstance(fjson, str):
|
|
54
|
+
with open(fjson, 'r') as f:
|
|
55
|
+
self.wjson = json.load(f)
|
|
56
|
+
else:
|
|
57
|
+
self.wjson = fjson
|
|
58
|
+
self._h5 = h5py.File(filename, 'r')
|
|
59
|
+
self.filename = filename
|
|
60
|
+
self.simulator = 'waiwera'
|
|
61
|
+
self.size_check = size_check # raise Exception if number of block does not match geo
|
|
62
|
+
self.setup()
|
|
63
|
+
|
|
64
|
+
def close(self):
|
|
65
|
+
self._h5.close()
|
|
66
|
+
|
|
67
|
+
def setup(self):
|
|
68
|
+
self.cell_idx = self._h5['cell_index'][:,0]
|
|
69
|
+
self.fulltimes = self._h5['time'][:,0]
|
|
70
|
+
self.num_fulltimes = len(self.fulltimes)
|
|
71
|
+
self._index = 0
|
|
72
|
+
### checks:
|
|
73
|
+
nh5 = len(self.cell_idx)
|
|
74
|
+
if self.geo is not None:
|
|
75
|
+
print('wlisting.element: uses mulgrid block name (str) as key.')
|
|
76
|
+
nb = self.geo.num_blocks - self.geo.num_atmosphere_blocks
|
|
77
|
+
if self.size_check and nh5 != nb:
|
|
78
|
+
msg = 'HDF5 result %s has %i cells different from geometry %s (%i excl. atmosphere blocks)' % (
|
|
79
|
+
self.filename, nh5, self.geo.filename, nb)
|
|
80
|
+
raise Exception(msg)
|
|
81
|
+
if nh5 < nb:
|
|
82
|
+
msg = 'HDF5 result %s has %i cells less than from geometry %s (%i excl. atmosphere blocks)' % (
|
|
83
|
+
self.filename, nh5, self.geo.filename, nb)
|
|
84
|
+
raise Exception(msg)
|
|
85
|
+
# blocks is seen by TIM/geo, w_blocks is used by waiwera-h5/json
|
|
86
|
+
blocks = self.geo.block_name_list
|
|
87
|
+
w_blocks = self.geo.block_name_list[self.geo.num_atmosphere_blocks:]
|
|
88
|
+
if nh5 > nb:
|
|
89
|
+
# assumes they are MINC blocks
|
|
90
|
+
blocks += [' '+str(i) for i in range(nh5 - nb)]
|
|
91
|
+
w_blocks += [' '+str(i) for i in range(nh5 - nb)]
|
|
92
|
+
else:
|
|
93
|
+
print('wlisting.element: uses waiwera natural index (as str) as key.')
|
|
94
|
+
blocks = [str(i) for i in range(nh5)]
|
|
95
|
+
w_blocks = blocks
|
|
96
|
+
### element table
|
|
97
|
+
if 'cell_fields' in self._h5:
|
|
98
|
+
cols = sorted([c for c in self._h5['cell_fields'].keys() if c.startswith('fluid_')])
|
|
99
|
+
table = listingtable(cols, blocks, num_keys=1)
|
|
100
|
+
self._table['element'] = table
|
|
101
|
+
### connection table
|
|
102
|
+
if 'face_fields' in self._h5:
|
|
103
|
+
cid1 = self._h5['face_cell_1'][:,0]
|
|
104
|
+
cid2 = self._h5['face_cell_2'][:,0]
|
|
105
|
+
# .face_idx equivalent to .cell_idx and .source_idx, which maps waiwera h5 table into
|
|
106
|
+
# geo/mulgrid order, there is no "natural order" of faces in waiwera, so we have to
|
|
107
|
+
# build one here
|
|
108
|
+
self.face_idx = []
|
|
109
|
+
self.face_idx_dir = []
|
|
110
|
+
if self.geo is not None:
|
|
111
|
+
print('wlisting.connection: tuple of mulgrid block names (str, str) as key.')
|
|
112
|
+
face_keys = self.geo.block_connection_name_list
|
|
113
|
+
# w_boundary is a list of dict, in the order of wjson boundaries, each dict has key
|
|
114
|
+
# of block1, gives name of b2.
|
|
115
|
+
w_boundary = []
|
|
116
|
+
if self.wjson is not None and 'boundaries' in self.wjson:
|
|
117
|
+
for bd in self.wjson['boundaries']:
|
|
118
|
+
b2_names = {}
|
|
119
|
+
for i1 in bd['faces']['cells']:
|
|
120
|
+
b1 = w_blocks[i1]
|
|
121
|
+
b2 = ' ' # default empty , overwritten if atmosphere
|
|
122
|
+
if bd['faces']['normal'] == [0.0, 0.0, 1.0]:
|
|
123
|
+
# if connect upwards, assume atmospheric, use mulgrid atm block names
|
|
124
|
+
b1_col = self.geo.column[self.geo.column_name(b1)]
|
|
125
|
+
b1_lay = self.geo.layer[self.geo.layer_name(b1)]
|
|
126
|
+
if self.geo.column_surface_layer(b1_col).name == b1_lay.name:
|
|
127
|
+
if self.geo.atmosphere_type == 0:
|
|
128
|
+
b2 = self.geo.block_name_list[0]
|
|
129
|
+
elif self.geo.atmosphere_type == 1:
|
|
130
|
+
b2 = self.geo.block_name(self.geo.layerlist[0].name, b1_col.name)
|
|
131
|
+
b2_names[b1] = b2
|
|
132
|
+
w_boundary.append(b2_names)
|
|
133
|
+
# this translate waiwera cell ids in (face_cell_1, face_cell_2) into block names
|
|
134
|
+
# w_connection_name_index has keys of (b1 name, b2 name), value is waiwera face index
|
|
135
|
+
# ordered as in h5 file
|
|
136
|
+
w_connection_name_index = {}
|
|
137
|
+
self.w_connection_index_index = {} # useful if given two waiwera cell indices
|
|
138
|
+
for i,(c1,c2) in enumerate(zip(cid1, cid2)):
|
|
139
|
+
self.w_connection_index_index[(c1,c2)] = i
|
|
140
|
+
b1 = w_blocks[c1]
|
|
141
|
+
if c2 < 0:
|
|
142
|
+
if w_boundary:
|
|
143
|
+
# face_cell_2 contains the negative of the (1-based) index of the boundaries
|
|
144
|
+
# specified in json
|
|
145
|
+
b2 = w_boundary[-c2-1][b1]
|
|
146
|
+
else:
|
|
147
|
+
# either wai JSON not loaded OR none are standard atm conne
|
|
148
|
+
b2 = ' '
|
|
149
|
+
# simply assumes atm conne if top of the model
|
|
150
|
+
b1_col = self.geo.column[self.geo.column_name(b1)]
|
|
151
|
+
b1_lay = self.geo.layer[self.geo.layer_name(b1)]
|
|
152
|
+
if self.geo.column_surface_layer(b1_col).name == b1_lay.name:
|
|
153
|
+
if self.geo.atmosphere_type == 0:
|
|
154
|
+
b2 = self.geo.block_name_list[0]
|
|
155
|
+
elif self.geo.atmosphere_type == 1:
|
|
156
|
+
b2 = self.geo.block_name(self.geo.layerlist[0].name, b1_col.name)
|
|
157
|
+
else:
|
|
158
|
+
b2 = w_blocks[c2]
|
|
159
|
+
w_connection_name_index[(b1,b2)] = i
|
|
160
|
+
for c in self.geo.block_connection_name_list:
|
|
161
|
+
# (cell1, cell2) positive means cell1 -> cell2
|
|
162
|
+
# NOTE this is opposite to T2/AUT2's result convention!
|
|
163
|
+
if c in w_connection_name_index:
|
|
164
|
+
self.face_idx.append(w_connection_name_index[c])
|
|
165
|
+
self.face_idx_dir.append(-1.0)
|
|
166
|
+
elif c[::-1] in w_connection_name_index:
|
|
167
|
+
self.face_idx.append(w_connection_name_index[c[::-1]])
|
|
168
|
+
self.face_idx_dir.append(1.0)
|
|
169
|
+
else:
|
|
170
|
+
debugxx = []
|
|
171
|
+
for key in w_connection_name_index:
|
|
172
|
+
if c[0] in key:
|
|
173
|
+
debugxx.append(key)
|
|
174
|
+
msg = str(debugxx)
|
|
175
|
+
msg += '\nMulgrid connection name %s not found in Waiwera H5 output.' % str(c)
|
|
176
|
+
raise Exception(msg)
|
|
177
|
+
else:
|
|
178
|
+
print('wlisting.connection: tuple of natural cell indices (as str, as str) as key.')
|
|
179
|
+
# keeps whatever order is in h5, NOTE the order is unpredictable
|
|
180
|
+
face_keys = [(str(i), str(j)) for i,j in zip(cid1, cid2)]
|
|
181
|
+
self.face_idx = list(range(len(cid1)))
|
|
182
|
+
self.face_idx_dir = [-1.0] * len(cid1)
|
|
183
|
+
|
|
184
|
+
self.face_idx_dir = np.array(self.face_idx_dir)
|
|
185
|
+
cols = sorted([c for c in self._h5['face_fields'].keys() if c.startswith('flux_')])
|
|
186
|
+
table = listingtable(cols, face_keys, num_keys=2, allow_reverse_keys=True)
|
|
187
|
+
self._table['connection'] = table
|
|
188
|
+
### gener table
|
|
189
|
+
if 'source_fields' in self._h5:
|
|
190
|
+
self.source_name_index = {} # allows either source name or (block name, gener name) as key
|
|
191
|
+
skip_cols = ['source_' + n for n in ['source_index', 'local_source_index', 'natural_cell_index', 'local_cell_index']]
|
|
192
|
+
cols = sorted([c for c in self._h5['source_fields'].keys() if c.startswith('source_') and c not in skip_cols])
|
|
193
|
+
self.source_idx = self._h5['source_index'][:,0]
|
|
194
|
+
source_keys = None
|
|
195
|
+
if self.geo is not None and self.wjson is not None:
|
|
196
|
+
if 'source' in self.wjson and len(self.wjson['source']) == len(self.source_idx):
|
|
197
|
+
if all(['name' in s for s in self.wjson['source']]) and all(['cell' in s for s in self.wjson['source']]):
|
|
198
|
+
# each source has a name, each source has a single cell
|
|
199
|
+
print('wlisting.generation: detects matching Waiwera input JSON and HDF5 source_fields, use (block name, source name) as key.')
|
|
200
|
+
cid = [w_blocks[s['cell']] for s in self.wjson['source']]
|
|
201
|
+
gid = [str(s['name']) for s in self.wjson['source']]
|
|
202
|
+
source_keys = list(zip(cid, gid))
|
|
203
|
+
for i,gk in enumerate(source_keys):
|
|
204
|
+
self.source_name_index[gk] = i
|
|
205
|
+
for i,s in enumerate(self.wjson['source']):
|
|
206
|
+
if 'name' in s:
|
|
207
|
+
self.source_name_index[s['name']] = i
|
|
208
|
+
if source_keys is None:
|
|
209
|
+
print('wlisting.generation: use source index (as str) as key.')
|
|
210
|
+
# use source index (as str) as key
|
|
211
|
+
source_keys = [str(i) for i in range(len(self.source_idx))]
|
|
212
|
+
table = listingtable(cols, source_keys, num_keys=1)
|
|
213
|
+
else:
|
|
214
|
+
# source_keys is (bname, gname) as in original t2listing
|
|
215
|
+
table = listingtable(cols, list(zip(cid, gid)), num_keys=2)
|
|
216
|
+
self._table['generation'] = table
|
|
217
|
+
# makes tables in self._table accessible as attributes
|
|
218
|
+
for key,table in self._table.items():
|
|
219
|
+
setattr(self, key, table)
|
|
220
|
+
# have to be get first table ready
|
|
221
|
+
self.index = 0
|
|
222
|
+
|
|
223
|
+
def history(self, selection, short=False, start_datetime=None):
|
|
224
|
+
""" Returns time histories for specified selection of table type, names
|
|
225
|
+
(or indices) and column names. This is implemented to be similar to
|
|
226
|
+
t2listing's .history().
|
|
227
|
+
|
|
228
|
+
('e', block name/index, column name)
|
|
229
|
+
for cell_fields, cell can be specified as Waiwera natural cell index
|
|
230
|
+
(int) or mulgrid's block name (str)
|
|
231
|
+
|
|
232
|
+
('c', (c1, c2), column name)
|
|
233
|
+
for face_fields, a face/connection can be specified by a tuple of
|
|
234
|
+
Waiwera's natural cell index (int, int) or mulgrid's block names
|
|
235
|
+
(str, str).
|
|
236
|
+
|
|
237
|
+
('g', g, column name) OR ('g', (b,g), column name)
|
|
238
|
+
for source_fields, a gener/source can be specified by an index
|
|
239
|
+
(int), a source name (str), or a tuple of (block name, source name)
|
|
240
|
+
((str, str)). The tuple option is only available if each source has
|
|
241
|
+
a name and each source has a single cell in the Waiwera JSON input.
|
|
242
|
+
|
|
243
|
+
short and start_datetime are not implemented at the moment
|
|
244
|
+
"""
|
|
245
|
+
if short is True: raise Exception('.history() short=True not implemented yet')
|
|
246
|
+
if start_datetime is not None: raise Exception('.history() start_datetime not implemented yet')
|
|
247
|
+
if isinstance(selection, tuple):
|
|
248
|
+
selection = [selection]
|
|
249
|
+
results = []
|
|
250
|
+
for tbl,b,cname in selection:
|
|
251
|
+
if tbl == 'e':
|
|
252
|
+
if isinstance(b, str):
|
|
253
|
+
bi = self.geo.block_name_index[b]
|
|
254
|
+
elif isinstance(b, int):
|
|
255
|
+
bi = b
|
|
256
|
+
else:
|
|
257
|
+
raise Exception('.history() block must be an int or str: %s (%s)' % (str(b),str(type(b))))
|
|
258
|
+
if bi < 0:
|
|
259
|
+
bi = self.geo.num_blocks + bi
|
|
260
|
+
if bi < self.geo.num_atmosphere_blocks:
|
|
261
|
+
raise Exception('.history() does not support extracting results for atmosphere blocks')
|
|
262
|
+
### important to convert cell index
|
|
263
|
+
bbi = self.cell_idx[bi-self.geo.num_atmosphere_blocks]
|
|
264
|
+
ys = self._h5['cell_fields'][cname][:,bbi]
|
|
265
|
+
results.append((self.fulltimes, ys))
|
|
266
|
+
elif tbl == 'c':
|
|
267
|
+
if isinstance(b[0], int):
|
|
268
|
+
# (i1, i2) assume both are integer cell index in Waiwera sense
|
|
269
|
+
cci = self.w_connection_index_index[b]
|
|
270
|
+
elif isinstance(b[0], str):
|
|
271
|
+
# (b1, b2) assume both are string block names in mulgrid
|
|
272
|
+
if self.geo is None:
|
|
273
|
+
raise Exception('Mulgrid geometry is required if connection tuple is specified by block names.')
|
|
274
|
+
ci = self.geo.block_connection_name_index[b]
|
|
275
|
+
cci = self.face_idx[ci]
|
|
276
|
+
ys = self._h5['face_fields'][cname][:,cci]
|
|
277
|
+
results.append((self.fulltimes, ys))
|
|
278
|
+
elif tbl == 'g':
|
|
279
|
+
if isinstance(b, tuple):
|
|
280
|
+
# (block name, source name) both str
|
|
281
|
+
gi = self.source_name_index[b]
|
|
282
|
+
elif isinstance(b, str):
|
|
283
|
+
# single natural source index !! diff from TOUGH2
|
|
284
|
+
gi = self.source_name_index[b]
|
|
285
|
+
if isinstance(b, int):
|
|
286
|
+
# directly as source index
|
|
287
|
+
gi = b
|
|
288
|
+
ggi = self.source_idx[gi]
|
|
289
|
+
ys = self._h5['source_fields'][cname][:,ggi]
|
|
290
|
+
results.append((self.fulltimes, ys))
|
|
291
|
+
else:
|
|
292
|
+
raise Exception('Unsupported .history() selection table type: %s' % tbl)
|
|
293
|
+
if len(results) == 1: results = results[0]
|
|
294
|
+
return results
|
|
295
|
+
|
|
296
|
+
def read_tables(self):
|
|
297
|
+
""" copy values from h5 into listingtables, with slicing """
|
|
298
|
+
if 'element' in self.table_names:
|
|
299
|
+
nh5 = len(self.cell_idx)
|
|
300
|
+
for i,cname in enumerate(self.element.column_name):
|
|
301
|
+
self.element._data[-nh5:,i] = self._h5['cell_fields'][cname][self._index][self.cell_idx]
|
|
302
|
+
if 'connection' in self.table_names:
|
|
303
|
+
for i,cname in enumerate(self.connection.column_name):
|
|
304
|
+
# re-order as geo.block_connection_name_list and reverse values if required
|
|
305
|
+
self.connection._data[:,i] = self._h5['face_fields'][cname][self._index][self.face_idx] * self.face_idx_dir
|
|
306
|
+
if 'generation' in self.table_names:
|
|
307
|
+
for i,cname in enumerate(self.generation.column_name):
|
|
308
|
+
self.generation._data[:,i] = self._h5['source_fields'][cname][self._index][self.source_idx]
|
|
309
|
+
|
|
310
|
+
def get_index(self): return self._index
|
|
311
|
+
def set_index(self, i):
|
|
312
|
+
self._index = i
|
|
313
|
+
if self._index < 0: self._index += self.num_fulltimes
|
|
314
|
+
self.read_tables()
|
|
315
|
+
index = property(get_index, set_index)
|
|
316
|
+
|
|
317
|
+
def first(self): self.index = 0
|
|
318
|
+
def last(self): self.index = -1
|
|
319
|
+
def next(self):
|
|
320
|
+
"""Find and read next set of results; returns false if at end of listing"""
|
|
321
|
+
more = self.index < self.num_fulltimes - 1
|
|
322
|
+
if more: self.index += 1
|
|
323
|
+
return more
|
|
324
|
+
def prev(self):
|
|
325
|
+
"""Find and read previous set of results; returns false if at start of listing"""
|
|
326
|
+
more = self.index > 0
|
|
327
|
+
if more: self.index -= 1
|
|
328
|
+
return more
|
|
329
|
+
|
|
330
|
+
def get_table_names(self):
|
|
331
|
+
return sorted(self._table.keys())
|
|
332
|
+
table_names = property(get_table_names)
|
|
333
|
+
|
|
334
|
+
def get_time(self): return self.fulltimes[self.index]
|
|
335
|
+
def set_time(self, t):
|
|
336
|
+
if t < self.fulltimes[0]: self.index = 0
|
|
337
|
+
elif t > self.fulltimes[-1]: self.index = -1
|
|
338
|
+
else:
|
|
339
|
+
dt = np.abs(self.fulltimes - t)
|
|
340
|
+
self.index = np.argmin(dt)
|
|
341
|
+
time = property(get_time, set_time)
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
class test_medium(unittest.TestCase):
|
|
345
|
+
def setUp(self):
|
|
346
|
+
from mulgrids import mulgrid
|
|
347
|
+
self.geo = mulgrid('g2medium.dat')
|
|
348
|
+
self.lst = wlisting('2DM002.h5', self.geo)
|
|
349
|
+
|
|
350
|
+
def test_atm_blocks(self):
|
|
351
|
+
self.assertEqual(len(self.lst.element.row_name), self.geo.num_blocks)
|
|
352
|
+
# atmosphere blocks should be zero
|
|
353
|
+
self.assertEqual(
|
|
354
|
+
list(self.lst.element['fluid_temperature'][:self.geo.num_atmosphere_blocks]),
|
|
355
|
+
[0.0] * self.geo.num_atmosphere_blocks)
|
|
356
|
+
# even after change index
|
|
357
|
+
self.index = 1
|
|
358
|
+
self.assertEqual(
|
|
359
|
+
list(self.lst.element['fluid_temperature'][:self.geo.num_atmosphere_blocks]),
|
|
360
|
+
[0.0] * self.geo.num_atmosphere_blocks)
|
|
361
|
+
|
|
362
|
+
def test_tables(self):
|
|
363
|
+
self.assertEqual(self.lst.table_names, ['element', 'generation'])
|
|
364
|
+
cols = [
|
|
365
|
+
'fluid_liquid_capillary_pressure',
|
|
366
|
+
'fluid_liquid_density',
|
|
367
|
+
'fluid_liquid_internal_energy',
|
|
368
|
+
'fluid_liquid_relative_permeability',
|
|
369
|
+
'fluid_liquid_saturation',
|
|
370
|
+
'fluid_liquid_specific_enthalpy',
|
|
371
|
+
'fluid_liquid_viscosity',
|
|
372
|
+
'fluid_liquid_water_mass_fraction',
|
|
373
|
+
'fluid_phases',
|
|
374
|
+
'fluid_pressure',
|
|
375
|
+
'fluid_region',
|
|
376
|
+
'fluid_temperature',
|
|
377
|
+
'fluid_vapour_capillary_pressure',
|
|
378
|
+
'fluid_vapour_density',
|
|
379
|
+
'fluid_vapour_internal_energy',
|
|
380
|
+
'fluid_vapour_relative_permeability',
|
|
381
|
+
'fluid_vapour_saturation',
|
|
382
|
+
'fluid_vapour_specific_enthalpy',
|
|
383
|
+
'fluid_vapour_viscosity',
|
|
384
|
+
'fluid_vapour_water_mass_fraction',
|
|
385
|
+
'fluid_water_partial_pressure']
|
|
386
|
+
self.assertEqual(sorted(self.lst.element.column_name), sorted(cols))
|
|
387
|
+
cols = [
|
|
388
|
+
'source_component',
|
|
389
|
+
'source_enthalpy',
|
|
390
|
+
'source_rate',
|
|
391
|
+
]
|
|
392
|
+
self.assertEqual(sorted(self.lst.generation.column_name), sorted(cols))
|
|
393
|
+
|
|
394
|
+
def test_basic_properties(self):
|
|
395
|
+
self.assertEqual(self.lst.num_fulltimes, 2)
|
|
396
|
+
np.testing.assert_almost_equal(
|
|
397
|
+
self.lst.fulltimes,
|
|
398
|
+
[0.0, 1.0E16],
|
|
399
|
+
decimal=7)
|
|
400
|
+
|
|
401
|
+
def test_index(self):
|
|
402
|
+
self.assertEqual(self.lst.index, 0)
|
|
403
|
+
self.assertAlmostEqual(self.lst.time, 0.0)
|
|
404
|
+
np.testing.assert_almost_equal(
|
|
405
|
+
self.lst.element['fluid_temperature'][-5:],
|
|
406
|
+
[15.0, 15.0, 15.0, 15.0, 15.0]
|
|
407
|
+
)
|
|
408
|
+
|
|
409
|
+
self.lst.index = 1
|
|
410
|
+
self.lst.index = 1
|
|
411
|
+
self.assertEqual(self.lst.index, 1)
|
|
412
|
+
self.assertAlmostEqual(self.lst.time, 1.0E16)
|
|
413
|
+
np.testing.assert_almost_equal(
|
|
414
|
+
self.lst.element['fluid_temperature'][-5:],
|
|
415
|
+
[235.7365710, 234.266913, 233.142164, 232.376319, 231.98525],
|
|
416
|
+
decimal=4
|
|
417
|
+
)
|
|
418
|
+
|
|
419
|
+
self.lst.index = 0
|
|
420
|
+
self.assertEqual(self.lst.index, 0)
|
|
421
|
+
self.assertAlmostEqual(self.lst.time, 0.0)
|
|
422
|
+
np.testing.assert_almost_equal(
|
|
423
|
+
self.lst.element['fluid_temperature'][-5:],
|
|
424
|
+
[15.0, 15.0, 15.0, 15.0, 15.0]
|
|
425
|
+
)
|
|
426
|
+
|
|
427
|
+
self.lst.index = -1
|
|
428
|
+
self.assertEqual(self.lst.index, 1)
|
|
429
|
+
self.assertAlmostEqual(self.lst.time, 1.0E16)
|
|
430
|
+
np.testing.assert_almost_equal(
|
|
431
|
+
self.lst.element['fluid_temperature'][-5:],
|
|
432
|
+
[235.7365710, 234.266913, 233.142164, 232.376319, 231.98525],
|
|
433
|
+
decimal=4
|
|
434
|
+
)
|
|
435
|
+
|
|
436
|
+
### generation
|
|
437
|
+
np.testing.assert_almost_equal(
|
|
438
|
+
self.lst.generation['source_rate'][:3],
|
|
439
|
+
[0.075, 0.075, 160.0],
|
|
440
|
+
decimal=4
|
|
441
|
+
)
|
|
442
|
+
np.testing.assert_almost_equal(
|
|
443
|
+
self.lst.generation['source_enthalpy'][:3],
|
|
444
|
+
[1200000.0, 1200000.0, 0.0],
|
|
445
|
+
decimal=4
|
|
446
|
+
)
|
|
447
|
+
np.testing.assert_almost_equal(
|
|
448
|
+
self.lst.generation['source_component'][:3],
|
|
449
|
+
[1.0, 1.0, 2.0],
|
|
450
|
+
decimal=4
|
|
451
|
+
)
|
|
452
|
+
|
|
453
|
+
def test_time(self):
|
|
454
|
+
self.lst.time = self.lst.fulltimes[1] - 100.0
|
|
455
|
+
self.assertEqual(self.lst.index, 1)
|
|
456
|
+
self.lst.time = 1.0e19
|
|
457
|
+
self.assertEqual(self.lst.index, 1)
|
|
458
|
+
self.lst.time = 0.0
|
|
459
|
+
self.assertEqual(self.lst.index, 0)
|
|
460
|
+
self.lst.time = 100.0
|
|
461
|
+
self.assertEqual(self.lst.index, 0)
|
|
462
|
+
|
|
463
|
+
def test_history(self):
|
|
464
|
+
# use relative tolerance, expect minor diff with different num of cpus
|
|
465
|
+
rtol = 1e-10
|
|
466
|
+
xs, ys = self.lst.history(('e', -1, 'fluid_pressure'))
|
|
467
|
+
np.testing.assert_allclose(xs, [0, 1.0e16], rtol=rtol)
|
|
468
|
+
np.testing.assert_allclose(ys, [101350.0, 1.3010923804323431E7], rtol=rtol)
|
|
469
|
+
xs, ys = self.lst.history(('e', 339, 'fluid_pressure'))
|
|
470
|
+
np.testing.assert_allclose(xs, [0, 1.0e16], rtol=rtol)
|
|
471
|
+
np.testing.assert_allclose(ys, [101350.0, 1.3010923804323431E7], rtol=rtol)
|
|
472
|
+
xs, ys = self.lst.history(('e', ' t16', 'fluid_pressure'))
|
|
473
|
+
np.testing.assert_allclose(xs, [0, 1.0e16], rtol=rtol)
|
|
474
|
+
np.testing.assert_allclose(ys, [101350.0, 1.3010923804323431E7], rtol=rtol)
|
|
475
|
+
xs, ys = self.lst.history(('e', 338, 'fluid_temperature'))
|
|
476
|
+
np.testing.assert_allclose(xs, [0, 1.0e16], rtol=rtol)
|
|
477
|
+
np.testing.assert_allclose(ys, [15.0, 232.3763193900396], rtol=rtol)
|
|
478
|
+
# cell index doesn't matter in generation
|
|
479
|
+
xs, ys = self.lst.history(('g', (999, 0), 'source_enthalpy'))
|
|
480
|
+
np.testing.assert_allclose(xs, [0, 1.0e16], rtol=rtol)
|
|
481
|
+
np.testing.assert_allclose(ys, [1200e3, 1200e3], rtol=rtol)
|
|
482
|
+
# also accepts single gener index int
|
|
483
|
+
xs, ys = self.lst.history(('g', 0, 'source_enthalpy'))
|
|
484
|
+
np.testing.assert_allclose(xs, [0, 1.0e16], rtol=rtol)
|
|
485
|
+
np.testing.assert_allclose(ys, [1200e3, 1200e3], rtol=rtol)
|
|
486
|
+
# also accepts gener index as str
|
|
487
|
+
xs, ys = self.lst.history(('g', '0', 'source_enthalpy'))
|
|
488
|
+
np.testing.assert_allclose(xs, [0, 1.0e16], rtol=rtol)
|
|
489
|
+
np.testing.assert_allclose(ys, [1200e3, 1200e3], rtol=rtol)
|
|
490
|
+
# cell index doesn't matter in generation
|
|
491
|
+
xs, ys = self.lst.history(('g', (999, '0'), 'source_enthalpy'))
|
|
492
|
+
np.testing.assert_allclose(xs, [0, 1.0e16], rtol=rtol)
|
|
493
|
+
np.testing.assert_allclose(ys, [1200e3, 1200e3], rtol=rtol)
|
|
494
|
+
tbl = self.lst.history([
|
|
495
|
+
('e', -1, 'fluid_pressure'),
|
|
496
|
+
('e', 339, 'fluid_pressure'),
|
|
497
|
+
('e', ' t16', 'fluid_pressure'),
|
|
498
|
+
('e', 338, 'fluid_temperature'),
|
|
499
|
+
('g', (999, 0), 'source_enthalpy'),
|
|
500
|
+
])
|
|
501
|
+
np.testing.assert_allclose(tbl[0][0], [0, 1.0e16], rtol=rtol)
|
|
502
|
+
np.testing.assert_allclose(tbl[0][1], [101350.0, 1.3010923804323431E7], rtol=rtol)
|
|
503
|
+
np.testing.assert_allclose(tbl[1][1], [101350.0, 1.3010923804323431E7], rtol=rtol)
|
|
504
|
+
np.testing.assert_allclose(tbl[2][1], [101350.0, 1.3010923804323431E7], rtol=rtol)
|
|
505
|
+
np.testing.assert_allclose(tbl[3][1], [15.0, 232.3763193900396], rtol=rtol)
|
|
506
|
+
np.testing.assert_allclose(tbl[4][1], [1200e3, 1200e3], rtol=rtol)
|
|
507
|
+
|
|
508
|
+
# should spit out an exception about not supporting atmosphere blocks
|
|
509
|
+
self.assertRaises(Exception, self.lst.history, ('e', 0, 'fluid_temperature'))
|
|
510
|
+
self.assertRaisesRegex(Exception, 'atmosphere', self.lst.history, ('e', 0, 'fluid_temperature'))
|
|
511
|
+
|
|
512
|
+
class test_medium_multiple_cpu(test_medium):
|
|
513
|
+
def setUp(self):
|
|
514
|
+
from mulgrids import mulgrid
|
|
515
|
+
self.geo = mulgrid('g2medium.dat')
|
|
516
|
+
self.lst = wlisting('2DM002a.h5', self.geo)
|
|
517
|
+
|
|
518
|
+
class test_compare(unittest.TestCase):
|
|
519
|
+
def setUp(self):
|
|
520
|
+
from mulgrids import mulgrid
|
|
521
|
+
self.geo = mulgrid('g2medium.dat')
|
|
522
|
+
self.lst1 = wlisting('2DM002.h5', self.geo)
|
|
523
|
+
self.lst2 = wlisting('2DM002a.h5', self.geo)
|
|
524
|
+
|
|
525
|
+
def test_table(self):
|
|
526
|
+
self.lst1.index = 1
|
|
527
|
+
self.lst2.index = 1
|
|
528
|
+
self.assertAlmostEqual(self.lst1.time, 1.0E16)
|
|
529
|
+
self.assertAlmostEqual(self.lst2.time, 1.0E16)
|
|
530
|
+
np.testing.assert_allclose(
|
|
531
|
+
self.lst1.element['fluid_temperature'],
|
|
532
|
+
self.lst2.element['fluid_temperature'],
|
|
533
|
+
rtol=1e-10,
|
|
534
|
+
equal_nan=True
|
|
535
|
+
)
|
|
536
|
+
np.testing.assert_allclose(
|
|
537
|
+
self.lst1.element['fluid_pressure'],
|
|
538
|
+
self.lst2.element['fluid_pressure'],
|
|
539
|
+
rtol=1e-10,
|
|
540
|
+
equal_nan=True
|
|
541
|
+
)
|
|
542
|
+
|
|
543
|
+
def test_history(self):
|
|
544
|
+
np.testing.assert_allclose(
|
|
545
|
+
self.lst1.history(('e', -1, 'fluid_pressure'))[1],
|
|
546
|
+
self.lst2.history(('e', -1, 'fluid_pressure'))[1],
|
|
547
|
+
rtol=1e-10,
|
|
548
|
+
)
|
|
549
|
+
np.testing.assert_allclose(
|
|
550
|
+
self.lst1.history(('e', 128, 'fluid_temperature'))[1],
|
|
551
|
+
self.lst2.history(('e', 128, 'fluid_temperature'))[1],
|
|
552
|
+
rtol=1e-10,
|
|
553
|
+
)
|
|
554
|
+
|
|
555
|
+
# check for false positive, this should be different
|
|
556
|
+
self.assertRaises(
|
|
557
|
+
AssertionError,
|
|
558
|
+
np.testing.assert_allclose,
|
|
559
|
+
self.lst1.history(('e', 123, 'fluid_pressure'))[1],
|
|
560
|
+
self.lst2.history(('e', 78, 'fluid_pressure'))[1],
|
|
561
|
+
rtol=1e-10,
|
|
562
|
+
)
|
|
563
|
+
self.assertRaises(
|
|
564
|
+
AssertionError,
|
|
565
|
+
np.testing.assert_allclose,
|
|
566
|
+
self.lst1.history(('e', 127, 'fluid_temperature'))[1],
|
|
567
|
+
self.lst2.history(('e', 128, 'fluid_temperature'))[1],
|
|
568
|
+
rtol=1e-10,
|
|
569
|
+
)
|
|
570
|
+
|
|
571
|
+
|
|
572
|
+
|
|
573
|
+
if __name__ == '__main__':
|
|
574
|
+
unittest.main(verbosity=2)
|
|
575
|
+
|
|
576
|
+
# import time
|
|
577
|
+
# from mulgrids import mulgrid
|
|
578
|
+
# geo = mulgrid('gLihir_v7_NS.dat')
|
|
579
|
+
# init_time = time.time()
|
|
580
|
+
# lst = wlisting('Lihir_v7_SP_NS_060_wai.h5', geo)
|
|
581
|
+
# print('%.2f sec' % (time.time() - init_time))
|
|
582
|
+
# init_time = time.time()
|
|
583
|
+
# lst.index = 1
|
|
584
|
+
# print('%.2f sec' % (time.time() - init_time))
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
|