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/run_ns_pr.py
ADDED
|
@@ -0,0 +1,617 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import os
|
|
3
|
+
import time
|
|
4
|
+
import re
|
|
5
|
+
import json
|
|
6
|
+
import tarfile
|
|
7
|
+
import subprocess
|
|
8
|
+
from shutil import copy2, move
|
|
9
|
+
from time import sleep
|
|
10
|
+
import importlib.util
|
|
11
|
+
import inspect
|
|
12
|
+
|
|
13
|
+
import numpy as np
|
|
14
|
+
import h5py
|
|
15
|
+
|
|
16
|
+
from mulgrids import *
|
|
17
|
+
from t2data import *
|
|
18
|
+
from t2listing import *
|
|
19
|
+
from t2incons import *
|
|
20
|
+
|
|
21
|
+
from gopest.utils import gener_groups
|
|
22
|
+
|
|
23
|
+
from gopest.common import config
|
|
24
|
+
from gopest.common import runtime
|
|
25
|
+
|
|
26
|
+
def tail(filename, n=10):
|
|
27
|
+
""" Return the last n lines of a file """
|
|
28
|
+
from collections import deque
|
|
29
|
+
return deque(open(filename), n)
|
|
30
|
+
|
|
31
|
+
def read_gener_file(fname):
|
|
32
|
+
f = t2data_parser(fname,'rU')
|
|
33
|
+
line = f.readline()
|
|
34
|
+
if line[:5] != 'GENER':
|
|
35
|
+
# get rid of first line 'GENER' and check
|
|
36
|
+
raise Exception("File %s is not a valid generator file, must starts with GENER." % fname)
|
|
37
|
+
gs = t2data()
|
|
38
|
+
gs.read_generators(f)
|
|
39
|
+
f.close()
|
|
40
|
+
return gs.generatorlist
|
|
41
|
+
|
|
42
|
+
def read_cols_in_zones(geo, fname='real_model.json'):
|
|
43
|
+
"""
|
|
44
|
+
NOTE WIP, need to deal with zone order in some cases (one zone includes another)
|
|
45
|
+
"""
|
|
46
|
+
with open(fname, 'rU') as jf:
|
|
47
|
+
cfg = json.load(jf)
|
|
48
|
+
col_zone = {}
|
|
49
|
+
for zone in cfg['ZonePolygon'].keys():
|
|
50
|
+
zone_polygon = [np.array(pt) for pt in cfg['ZonePolygon'][zone]]
|
|
51
|
+
for c in geo.columns_in_polygon(zone_polygon):
|
|
52
|
+
col_zone[c.name] = zone
|
|
53
|
+
return col_zone
|
|
54
|
+
|
|
55
|
+
def save_bad_model(dat, sav):
|
|
56
|
+
""" keep a model and its incon aside for later inspection, iused in the
|
|
57
|
+
case of difficult to converge.
|
|
58
|
+
"""
|
|
59
|
+
archive_dir = 'bad_models'
|
|
60
|
+
def next_unused_dir():
|
|
61
|
+
from os.path import isdir, isfile, join
|
|
62
|
+
i = 1
|
|
63
|
+
p = join(archive_dir, str(i))
|
|
64
|
+
while isdir(p) or isfile(p):
|
|
65
|
+
i += 1
|
|
66
|
+
p = join(archive_dir, str(i))
|
|
67
|
+
return p
|
|
68
|
+
psave = next_unused_dir()
|
|
69
|
+
os.makedirs(psave)
|
|
70
|
+
dat.write(psave + os.sep + 'real_model.dat')
|
|
71
|
+
sav.write(psave + os.sep + 'real_model.incon')
|
|
72
|
+
|
|
73
|
+
def targz_files(files, default_name):
|
|
74
|
+
""" add files into a compressed tar file (.tar.gz). File name will be
|
|
75
|
+
default_name with a number. The number will be incremented if other tar
|
|
76
|
+
file existed based on the same name.
|
|
77
|
+
"""
|
|
78
|
+
i = 1
|
|
79
|
+
f = default_name + str(i) + ".tar.gz"
|
|
80
|
+
while os.path.isfile(f):
|
|
81
|
+
i += 1
|
|
82
|
+
f = default_name + str(i) + ".tar.gz"
|
|
83
|
+
tar = tarfile.open(f, 'w:gz')
|
|
84
|
+
for name in files:
|
|
85
|
+
if os.path.isfile(name) or os.path.isdir(name):
|
|
86
|
+
tar.add(name)
|
|
87
|
+
tar.close()
|
|
88
|
+
return f
|
|
89
|
+
|
|
90
|
+
def fix_base_heat(dat, geo):
|
|
91
|
+
fname = 'real_model.json'
|
|
92
|
+
col_zone = read_cols_in_zones(geo, fname=fname)
|
|
93
|
+
with open(fname, 'r') as jf:
|
|
94
|
+
cfg = json.load(jf)
|
|
95
|
+
for g in dat.generatorlist:
|
|
96
|
+
if g.name.endswith('99') and g.type == 'HEAT':
|
|
97
|
+
col = geo.column[geo.column_name(g.block)]
|
|
98
|
+
if col.name in col_zone:
|
|
99
|
+
v = cfg['HeatFlux'][col_zone[col.name]]
|
|
100
|
+
else:
|
|
101
|
+
v = cfg['HeatFlux']['Default']
|
|
102
|
+
g.gx = col.area * v
|
|
103
|
+
return dat
|
|
104
|
+
|
|
105
|
+
def fix_co2_mass_ratio(dat):
|
|
106
|
+
# ohaaki seems to use 4%, have not checked with Mike yet
|
|
107
|
+
# CO2_MASS_RATIO = 0.04
|
|
108
|
+
with open('data_co2_ratio.json', 'r') as f:
|
|
109
|
+
ratio = json.load(f)
|
|
110
|
+
mass = {}
|
|
111
|
+
for g in dat.generatorlist:
|
|
112
|
+
if g.block.endswith('61') and g.name.endswith('77') and g.type == 'MASS':
|
|
113
|
+
mass[g.block] = g.gx
|
|
114
|
+
for g in dat.generatorlist:
|
|
115
|
+
if g.block.endswith('61') and g.name.endswith('66') and g.type == 'COM2':
|
|
116
|
+
# g.gx = mass[g.block] * CO2_MASS_RATIO
|
|
117
|
+
g.gx = mass[g.block] * ratio[g.block]
|
|
118
|
+
return dat
|
|
119
|
+
|
|
120
|
+
def set_output_times(dat, print_every=31558000.0):
|
|
121
|
+
""" a year is actually 31557600 sec, but precision will be lost, so it would
|
|
122
|
+
be 31558000 that actually used. """
|
|
123
|
+
dat.output_times.update({
|
|
124
|
+
'max_timestep': 0.0,
|
|
125
|
+
'num_times': 1000,
|
|
126
|
+
'num_times_specified': 1,
|
|
127
|
+
'time': [print_every],
|
|
128
|
+
'time_increment': print_every,
|
|
129
|
+
})
|
|
130
|
+
dat.parameter.update({
|
|
131
|
+
'max_timesteps': -999, # unlimited
|
|
132
|
+
'print_interval': -999, # do not print with MCYPR
|
|
133
|
+
})
|
|
134
|
+
dat.parameter['option'][24] = 2
|
|
135
|
+
dat.parameter['option'][16] = 5
|
|
136
|
+
return dat
|
|
137
|
+
|
|
138
|
+
def ensure_converge(ns, sav, allow_failed_ns=True):
|
|
139
|
+
# re-run until taget time reached, max 3 times.
|
|
140
|
+
from os.path import splitext
|
|
141
|
+
datbase,ext = splitext(ns.filename)
|
|
142
|
+
target_ns_time = ns.parameter['tstop']
|
|
143
|
+
run = 0
|
|
144
|
+
while abs(sav.timing['sumtim'] - target_ns_time) > 1000 and run < 0:
|
|
145
|
+
run += 1
|
|
146
|
+
print('Warning NS ends at %e sec, did not reach target time: %e, re-run NS for %ith time.' % (float(sav.timing['sumtim']), float(target_ns_time), run))
|
|
147
|
+
ns.write(datbase+"_rerun.dat", echo_extra_precision=True)
|
|
148
|
+
sav.write(datbase+"_rerun.incon", reset=True)
|
|
149
|
+
ns.run(simulator=simulator, silent=silent)
|
|
150
|
+
sav = t2incon(datbase+"_rerun.save")
|
|
151
|
+
if abs(sav.timing['sumtim'] - target_ns_time) > 1000:
|
|
152
|
+
print('Warning NS ends at %e sec, still not reach target time: %e, after %ith tries.' % (float(sav.timing['sumtim']), float(target_ns_time), run))
|
|
153
|
+
tfname = targz_files([datbase+'.dat', datbase+'.pdat', datbase+'.incon'],
|
|
154
|
+
'bad_model_')
|
|
155
|
+
print(tfname, 'saved')
|
|
156
|
+
if not allow_failed_ns:
|
|
157
|
+
return False
|
|
158
|
+
return sav
|
|
159
|
+
|
|
160
|
+
def del_files_no_check(files):
|
|
161
|
+
for cf in files:
|
|
162
|
+
try:
|
|
163
|
+
os.remove(cf)
|
|
164
|
+
except OSError:
|
|
165
|
+
pass
|
|
166
|
+
|
|
167
|
+
def run_user_pre(seq):
|
|
168
|
+
""" run user supplied pre-processing function if exists """
|
|
169
|
+
file_path = 'goPESTuser.py'
|
|
170
|
+
module_name = 'user'
|
|
171
|
+
if os.path.exists(file_path):
|
|
172
|
+
spec = importlib.util.spec_from_file_location(module_name, file_path)
|
|
173
|
+
module = importlib.util.module_from_spec(spec)
|
|
174
|
+
sys.modules[module_name] = module
|
|
175
|
+
spec.loader.exec_module(module)
|
|
176
|
+
for name,func in inspect.getmembers(module, inspect.isfunction):
|
|
177
|
+
print('%s has user func: %s()' % (file_path, name))
|
|
178
|
+
if name == 'pre_' + seq:
|
|
179
|
+
print(' -> calling %s() ...' % name)
|
|
180
|
+
func()
|
|
181
|
+
break
|
|
182
|
+
|
|
183
|
+
def run_ns_pr_waiwera(skippr=False, sav2inc=False, simulator='waiwera-dkr',
|
|
184
|
+
allow_failed_ns=True, silent=True):
|
|
185
|
+
"""
|
|
186
|
+
supported platforms:
|
|
187
|
+
'waiwera' - local native waiwera executable
|
|
188
|
+
'waiwera-dkr' - local waiwera running on docker
|
|
189
|
+
'waiwera-Maui' - NeSI Maui (uses submit_beopest.py)
|
|
190
|
+
'waiwera-Mahuika' - NeSI Mahuika (uses submit_beopest.py)
|
|
191
|
+
"""
|
|
192
|
+
fgeo = runtime['filename']['geom']
|
|
193
|
+
fsav = runtime['filename']['save']
|
|
194
|
+
finc = runtime['filename']['incon']
|
|
195
|
+
fdato = runtime['filename']['dat_orig']
|
|
196
|
+
fdats = runtime['filename']['dat_seq']
|
|
197
|
+
flsts = runtime['filename']['lst_seq']
|
|
198
|
+
sequence = config['model']['sequence']
|
|
199
|
+
|
|
200
|
+
if os.path.exists(finc):
|
|
201
|
+
# check incon
|
|
202
|
+
inc_h5 = h5py.File(finc, 'r')
|
|
203
|
+
inc_idx = len(inc_h5['time'][:,0]) - 1
|
|
204
|
+
if inc_idx < 0:
|
|
205
|
+
inc_h5.close()
|
|
206
|
+
raise Exception("ERROR! Waiwera initial conditions file '%s' has no data." % finc)
|
|
207
|
+
inc_h5.close()
|
|
208
|
+
else:
|
|
209
|
+
raise Exception("Error! Waiwera initial conditions file '%s' not found." % finc)
|
|
210
|
+
|
|
211
|
+
# call user pre-processing
|
|
212
|
+
# user is responsible of reading/writing files
|
|
213
|
+
run_user_pre(sequence[0])
|
|
214
|
+
|
|
215
|
+
with open(fdats[0], 'r') as f:
|
|
216
|
+
wai_ns = json.load(f)
|
|
217
|
+
# overwrite these just to be safe
|
|
218
|
+
wai_ns["output"]["filename"] = flsts[0]
|
|
219
|
+
wai_ns["mesh"]["filename"] = "g_real_model.msh"
|
|
220
|
+
wai_ns["initial"] = {"filename": finc, "index": inc_idx}
|
|
221
|
+
if silent:
|
|
222
|
+
wai_ns["logfile"] = {"echo": False}
|
|
223
|
+
else:
|
|
224
|
+
wai_ns["logfile"] = {"echo": True}
|
|
225
|
+
with open(fdats[0], 'w') as f:
|
|
226
|
+
json.dump(wai_ns, f, indent=2, sort_keys=True)
|
|
227
|
+
|
|
228
|
+
# clean up
|
|
229
|
+
del_files_no_check([
|
|
230
|
+
flsts[0],
|
|
231
|
+
fdats[0].replace('.json', '.yaml'),
|
|
232
|
+
])
|
|
233
|
+
|
|
234
|
+
model_args = [fdats[0]] + config['simulator']['cmd-options']
|
|
235
|
+
if config['mode'] == 'local':
|
|
236
|
+
cmd = [config['simulator']['executable']] + model_args
|
|
237
|
+
else:
|
|
238
|
+
cmd = ['gopest', 'submit', '--forward3x', ' '.join(model_args)]
|
|
239
|
+
|
|
240
|
+
START_TIME = time.time()
|
|
241
|
+
print('NS launched on %s...' % config['mode'])
|
|
242
|
+
# run NS
|
|
243
|
+
print(cmd)
|
|
244
|
+
subprocess.call(cmd)
|
|
245
|
+
|
|
246
|
+
# check NS
|
|
247
|
+
if os.path.exists(flsts[0]):
|
|
248
|
+
inc_h5 = h5py.File(flsts[0], 'r')
|
|
249
|
+
inc_idx = len(inc_h5['time'][:,0]) - 1
|
|
250
|
+
if inc_idx < 0:
|
|
251
|
+
raise Exception("ERROR! output file '%s' has no data." % flsts[0])
|
|
252
|
+
endtime = inc_h5['time'][inc_idx, 0]
|
|
253
|
+
inc_h5.close()
|
|
254
|
+
if abs(endtime - wai_ns['time']['stop']) < 1.e3:
|
|
255
|
+
print('NS finished after %.1f seconds' % (time.time() - START_TIME))
|
|
256
|
+
else:
|
|
257
|
+
print('NS failed after %.1f seconds' % (time.time() - START_TIME))
|
|
258
|
+
if not allow_failed_ns:
|
|
259
|
+
return False
|
|
260
|
+
else:
|
|
261
|
+
raise Exception('NS failed, result %s not found.' % flsts[0])
|
|
262
|
+
|
|
263
|
+
if skippr:
|
|
264
|
+
msg = 'Skipped PR, use NS result as PR for goPESTobs/pest_model'
|
|
265
|
+
print(msg)
|
|
266
|
+
return True
|
|
267
|
+
|
|
268
|
+
# call user pre-processing
|
|
269
|
+
# user is responsible of reading/writing files
|
|
270
|
+
run_user_pre(sequence[-1])
|
|
271
|
+
|
|
272
|
+
with open(fdats[-1], 'r') as f:
|
|
273
|
+
wai_pr = json.load(f)
|
|
274
|
+
wai_pr['output']['filename'] = flsts[-1]
|
|
275
|
+
wai_pr["initial"] = {"filename": flsts[0], "index": inc_idx}
|
|
276
|
+
wai_pr["mesh"]["filename"] = "g_real_model.msh"
|
|
277
|
+
if silent:
|
|
278
|
+
wai_pr["logfile"] = {"echo": False}
|
|
279
|
+
else:
|
|
280
|
+
wai_pr["logfile"] = {"echo": True}
|
|
281
|
+
with open(fdats[-1], 'w') as f:
|
|
282
|
+
json.dump(wai_pr, f, indent=2, sort_keys=True)
|
|
283
|
+
|
|
284
|
+
# clean up
|
|
285
|
+
del_files_no_check([
|
|
286
|
+
flsts[-1],
|
|
287
|
+
fdats[-1].replace('.json', '.yaml'),
|
|
288
|
+
])
|
|
289
|
+
|
|
290
|
+
model_args = [fdats[-1]] + config['simulator']['cmd-options']
|
|
291
|
+
if config['mode'] == 'local':
|
|
292
|
+
cmd = [config['executable']] + model_args
|
|
293
|
+
else:
|
|
294
|
+
cmd = ['gopest', 'submit', '--forward3x', ' '.join(model_args)]
|
|
295
|
+
|
|
296
|
+
START_TIME = time.time()
|
|
297
|
+
print('PR launched on %s...' % simulator)
|
|
298
|
+
# run
|
|
299
|
+
print(cmd)
|
|
300
|
+
subprocess.call(cmd)
|
|
301
|
+
|
|
302
|
+
# check PR
|
|
303
|
+
if os.path.exists(flsts[-1]):
|
|
304
|
+
inc_h5 = h5py.File(flsts[-1], 'r')
|
|
305
|
+
inc_idx = len(inc_h5['time'][:,0]) - 1
|
|
306
|
+
if inc_idx < 0:
|
|
307
|
+
raise Exception("ERROR! output file '%s' has no data." % flsts[-1])
|
|
308
|
+
endtime = inc_h5['time'][inc_idx, 0]
|
|
309
|
+
inc_h5.close()
|
|
310
|
+
if abs(endtime - wai_pr['time']['stop']) < 1.e3:
|
|
311
|
+
print('PR finished after %.1f seconds' % (time.time() - START_TIME))
|
|
312
|
+
else:
|
|
313
|
+
print('PR failed after %.1f seconds' % (time.time() - START_TIME))
|
|
314
|
+
if not allow_failed_ns:
|
|
315
|
+
return False
|
|
316
|
+
else:
|
|
317
|
+
raise Exception('PR failed, result %s not found.' % flsts[-1])
|
|
318
|
+
|
|
319
|
+
return True
|
|
320
|
+
|
|
321
|
+
def run_ns_pr_mixed(skippr=False, sav2inc=False, simulator='waiwera-dkr',
|
|
322
|
+
allow_failed_ns=True, silent=True):
|
|
323
|
+
""" convert aut2 model into waiwera, and run ns/pr
|
|
324
|
+
|
|
325
|
+
supported platforms:
|
|
326
|
+
'waiwera' - local native waiwera executable
|
|
327
|
+
'waiwera-dkr' - local waiwera running on docker
|
|
328
|
+
'waiwera-Maui' - NeSI Maui (uses submit_beopest.py)
|
|
329
|
+
'waiwera-Mahuika' - NeSI Mahuika (uses submit_beopest.py)
|
|
330
|
+
"""
|
|
331
|
+
geo = mulgrid("g_real_model.dat")
|
|
332
|
+
inc = t2incon("real_model.incon")
|
|
333
|
+
inc.porosity = None
|
|
334
|
+
inc.write("real_model.incon", reset=True)
|
|
335
|
+
inc = t2incon("real_model.incon")
|
|
336
|
+
t2_ns = t2data("real_model.dat")
|
|
337
|
+
t2_ns = fix_co2_mass_ratio(t2_ns)
|
|
338
|
+
t2_ns.write(echo_extra_precision=True)
|
|
339
|
+
|
|
340
|
+
if os.path.exists('real_model.incon.h5'):
|
|
341
|
+
# check incon
|
|
342
|
+
inc_h5 = h5py.File('real_model.incon.h5', 'r')
|
|
343
|
+
inc_idx = len(inc_h5['time'][:,0]) - 1
|
|
344
|
+
if inc_idx < 0:
|
|
345
|
+
raise Exception("ERROR! Waiwera initial conditions file 'real_model.incon.h5' has no data.")
|
|
346
|
+
inc_h5.close()
|
|
347
|
+
use_inc = '--' # use dummy in dat.json(), then replaced later
|
|
348
|
+
else:
|
|
349
|
+
print('real_model.incon.h5 does not exist, use T2 real_model.incon instead.')
|
|
350
|
+
use_inc = inc
|
|
351
|
+
|
|
352
|
+
wai_ns = t2_ns.json(geo, 'g_real_model.msh',
|
|
353
|
+
atmos_volume=1.e25,
|
|
354
|
+
incons=use_inc,
|
|
355
|
+
eos=None,
|
|
356
|
+
bdy_incons=inc, # somehow I still need it to avoid error
|
|
357
|
+
mesh_coords='xyz')
|
|
358
|
+
|
|
359
|
+
wai_ns_orig = json.load(open('real_model_original.json', 'r'))
|
|
360
|
+
for k in ["time", "output", "mesh"]:
|
|
361
|
+
wai_ns[k] = wai_ns_orig[k]
|
|
362
|
+
|
|
363
|
+
# overwrite these just to be safe
|
|
364
|
+
wai_ns["thermodynamics"] = {"name": "ifc67", "extrapolate": True}
|
|
365
|
+
wai_ns["output"]["filename"] = "real_model.h5"
|
|
366
|
+
wai_ns["output"]["frequency"] = 1000
|
|
367
|
+
wai_ns["time"]["step"]["maximum"]["number"] = 80000
|
|
368
|
+
wai_ns["time"]["stop"] = 0.5e14
|
|
369
|
+
wai_ns["mesh"]["filename"] = "g_real_model.msh"
|
|
370
|
+
if use_inc == '--':
|
|
371
|
+
wai_ns["initial"] = {"filename": "real_model.incon.h5", "index": inc_idx}
|
|
372
|
+
|
|
373
|
+
json.dump(wai_ns, open('real_model.json', 'w'), indent=2, sort_keys=True)
|
|
374
|
+
|
|
375
|
+
# clean up
|
|
376
|
+
clean_files = [
|
|
377
|
+
'real_model.h5',
|
|
378
|
+
'real_model.save',
|
|
379
|
+
'real_model.listing',
|
|
380
|
+
]
|
|
381
|
+
for cf in clean_files:
|
|
382
|
+
try:
|
|
383
|
+
os.remove(cf)
|
|
384
|
+
except OSError:
|
|
385
|
+
pass
|
|
386
|
+
model_cmd = [
|
|
387
|
+
'real_model.json',
|
|
388
|
+
'-ksp_type', 'bcgsl',
|
|
389
|
+
'-snes_ksp_ew',
|
|
390
|
+
'-snes_ksp_ew_rtol0', '1e-5',
|
|
391
|
+
'-snes_ksp_ew_rtolmax', '1e-4',
|
|
392
|
+
'-pc_type', 'asm',
|
|
393
|
+
'-pc_factor_levels', '1',
|
|
394
|
+
'-snes_max_linear_solve_fail', '3',
|
|
395
|
+
]
|
|
396
|
+
NP = 4
|
|
397
|
+
cmd = {
|
|
398
|
+
'waiwera': ['mpiexec', '-np', str(NP), 'waiwera', '-np'] + model_cmd,
|
|
399
|
+
'waiwera-dkr': ['waiwera-dkr', '-np', str(NP), '--tag', 'testing'] + model_cmd,
|
|
400
|
+
'waiwera-Maui': ['python', 'submit_beopest.py', '--forward3maui', ' '.join(['~/bin/waiwera-maui']+model_cmd)],
|
|
401
|
+
'waiwera-Mahuika': ['python', 'submit_beopest.py', '--forward3mahuika', ' '.join(['~/bin-mahuika/waiwera']+model_cmd)],
|
|
402
|
+
}[simulator]
|
|
403
|
+
START_TIME = time.time()
|
|
404
|
+
print('NS launched on %s...' % simulator)
|
|
405
|
+
# run NS
|
|
406
|
+
print(cmd)
|
|
407
|
+
subprocess.call(cmd)
|
|
408
|
+
|
|
409
|
+
# check NS
|
|
410
|
+
if os.path.exists('real_model.h5'):
|
|
411
|
+
inc_h5 = h5py.File('real_model.h5', 'r')
|
|
412
|
+
inc_idx = len(inc_h5['time'][:,0]) - 1
|
|
413
|
+
if inc_idx < 0:
|
|
414
|
+
raise Exception("ERROR! output file 'real_model.h5' has no data.")
|
|
415
|
+
endtime = inc_h5['time'][inc_idx, 0]
|
|
416
|
+
inc_h5.close()
|
|
417
|
+
if abs(endtime - wai_ns['time']['stop']) < 1.e3:
|
|
418
|
+
print('NS finished after %.1f seconds' % (time.time() - START_TIME))
|
|
419
|
+
else:
|
|
420
|
+
print('NS failed after %.1f seconds' % (time.time() - START_TIME))
|
|
421
|
+
if not allow_failed_ns:
|
|
422
|
+
return False
|
|
423
|
+
|
|
424
|
+
if skippr:
|
|
425
|
+
copy2('real_model.h5', 'real_model_pr.h5')
|
|
426
|
+
msg = 'Skipped PR, use NS result as PR for goPESTobs/pest_model'
|
|
427
|
+
print(msg)
|
|
428
|
+
return True
|
|
429
|
+
|
|
430
|
+
# change NS to PR
|
|
431
|
+
wai_pr = wai_ns
|
|
432
|
+
with open('gs_production.json', 'r') as f:
|
|
433
|
+
data = json.load(f)
|
|
434
|
+
wai_pr['source'] = wai_pr['source'] + data
|
|
435
|
+
with open('real_model_pr.output.json', 'r') as f:
|
|
436
|
+
data = json.load(f)
|
|
437
|
+
wai_pr['output'] = data
|
|
438
|
+
with open('real_model_pr.time.json', 'r') as f:
|
|
439
|
+
data = json.load(f)
|
|
440
|
+
wai_pr['time'] = data
|
|
441
|
+
# additional
|
|
442
|
+
wai_pr['output']['filename'] = 'real_model_pr.h5'
|
|
443
|
+
wai_pr['output']['frequency'] = 0
|
|
444
|
+
wai_pr["initial"] = {"filename": "real_model.h5", "index": inc_idx}
|
|
445
|
+
|
|
446
|
+
json.dump(wai_pr, open('real_model_pr.json', 'w'), indent=2, sort_keys=True)
|
|
447
|
+
|
|
448
|
+
# clean up
|
|
449
|
+
clean_files = [
|
|
450
|
+
'real_model_pr.h5',
|
|
451
|
+
'real_model_pr.save',
|
|
452
|
+
'real_model_pr.listing',
|
|
453
|
+
]
|
|
454
|
+
for cf in clean_files:
|
|
455
|
+
try:
|
|
456
|
+
os.remove(cf)
|
|
457
|
+
except OSError:
|
|
458
|
+
pass
|
|
459
|
+
START_TIME = time.time()
|
|
460
|
+
print('PR launched on %s...' % simulator)
|
|
461
|
+
model_cmd = [
|
|
462
|
+
'real_model_pr.json',
|
|
463
|
+
'-ksp_type', 'bcgsl',
|
|
464
|
+
'-snes_ksp_ew',
|
|
465
|
+
'-snes_ksp_ew_rtol0', '1e-5',
|
|
466
|
+
'-snes_ksp_ew_rtolmax', '1e-4',
|
|
467
|
+
'-pc_type', 'asm',
|
|
468
|
+
'-pc_factor_levels', '1',
|
|
469
|
+
'-snes_max_linear_solve_fail', '3',
|
|
470
|
+
]
|
|
471
|
+
NP = 4
|
|
472
|
+
cmd = {
|
|
473
|
+
'waiwera': ['mpiexec', '-np', str(NP), 'waiwera', '-np'] + model_cmd,
|
|
474
|
+
'waiwera-dkr': ['waiwera-dkr', '-np', str(NP), '--tag', 'testing'] + model_cmd,
|
|
475
|
+
'waiwera-Maui': ['python', 'submit_beopest.py', '--forward3maui', ' '.join(['~/bin/waiwera-maui']+model_cmd)],
|
|
476
|
+
'waiwera-Mahuika': ['python', 'submit_beopest.py', '--forward3mahuika', ' '.join(['~/bin-mahuika/waiwera']+model_cmd)],
|
|
477
|
+
}[simulator]
|
|
478
|
+
# run
|
|
479
|
+
print('Running PR ...')
|
|
480
|
+
print(cmd)
|
|
481
|
+
START_TIME = time.time()
|
|
482
|
+
subprocess.call(cmd)
|
|
483
|
+
|
|
484
|
+
# check PR
|
|
485
|
+
if os.path.exists('real_model_pr.h5'):
|
|
486
|
+
inc_h5 = h5py.File('real_model_pr.h5', 'r')
|
|
487
|
+
inc_idx = len(inc_h5['time'][:,0]) - 1
|
|
488
|
+
if inc_idx < 0:
|
|
489
|
+
raise Exception("ERROR! output file 'real_model.h5' has no data.")
|
|
490
|
+
endtime = inc_h5['time'][inc_idx, 0]
|
|
491
|
+
inc_h5.close()
|
|
492
|
+
if abs(endtime - wai_pr['time']['stop']) < 1.e3:
|
|
493
|
+
print('PR finished after %.1f seconds' % (time.time() - START_TIME))
|
|
494
|
+
else:
|
|
495
|
+
print('PR failed after %.1f seconds' % (time.time() - START_TIME))
|
|
496
|
+
if not allow_failed_ns:
|
|
497
|
+
return False
|
|
498
|
+
# fake a dummy real_model_pr.dat (for goPESTobs.py), need to check not used by those obs types
|
|
499
|
+
t2_ns.write('real_model_pr.dat', echo_extra_precision=True)
|
|
500
|
+
return True
|
|
501
|
+
|
|
502
|
+
def run_ns_pr_aut2(skippr=False, sav2inc=False, simulator='AUTOUGH2_3D',
|
|
503
|
+
allow_failed_ns=True, silent=True):
|
|
504
|
+
# fgeo = runtime['filename']['geom']
|
|
505
|
+
finc = runtime['filename']['incon']
|
|
506
|
+
fdats = runtime['filename']['dat_seq']
|
|
507
|
+
flsts = runtime['filename']['lst_seq']
|
|
508
|
+
fincs = runtime['filename']['inc_seq']
|
|
509
|
+
fsavs = runtime['filename']['sav_seq']
|
|
510
|
+
sequence = config['model']['sequence']
|
|
511
|
+
|
|
512
|
+
silent = config['model']['silent']
|
|
513
|
+
print(' -- aut2: %s is used. (silent=%s)' % (simulator, str(silent)))
|
|
514
|
+
|
|
515
|
+
# geo = mulgrid("g_real_model.dat")
|
|
516
|
+
sav = t2incon(finc)
|
|
517
|
+
|
|
518
|
+
for iseq,seq in enumerate(sequence):
|
|
519
|
+
sav.porosity = None
|
|
520
|
+
sav.write(fincs[iseq], reset=True)
|
|
521
|
+
inc = t2incon(fincs[iseq])
|
|
522
|
+
|
|
523
|
+
# call user pre-processing
|
|
524
|
+
# user is responsible of reading/writing files
|
|
525
|
+
run_user_pre(seq)
|
|
526
|
+
|
|
527
|
+
ns = t2data(fdats[iseq])
|
|
528
|
+
ns.write(echo_extra_precision=True)
|
|
529
|
+
|
|
530
|
+
START_TIME = time.time()
|
|
531
|
+
ns.run(simulator=simulator, silent=silent)
|
|
532
|
+
sav = t2incon(fsavs[iseq])
|
|
533
|
+
if seq == 'ns':
|
|
534
|
+
sav = ensure_converge(ns, sav, allow_failed_ns)
|
|
535
|
+
if sav is False:
|
|
536
|
+
return False
|
|
537
|
+
if sav2inc:
|
|
538
|
+
sav.write("real_model.incon", reset=True)
|
|
539
|
+
print(' - %s finished after ' % seq, (time.time() - START_TIME), 'seconds')
|
|
540
|
+
|
|
541
|
+
# if skippr:
|
|
542
|
+
# # fake real_model_pr.* because thats what pest_model.py will apply goPESTobs on
|
|
543
|
+
# copy2('real_model.dat', 'real_model_pr.dat')
|
|
544
|
+
# copy2('real_model.pdat', 'real_model_pr.pdat')
|
|
545
|
+
# copy2('real_model.listing', 'real_model_pr.listing')
|
|
546
|
+
# msg = 'Skipped PR, make sure to use NS result as PR for goPESTobs/pest_model'
|
|
547
|
+
# print(msg)
|
|
548
|
+
# return True
|
|
549
|
+
|
|
550
|
+
# ##### everything below is production run
|
|
551
|
+
# pr = t2data("real_model_original_pr.dat")
|
|
552
|
+
# target_pr_time = pr.parameter['tstop']
|
|
553
|
+
# # pr = set_output_times(pr, 15779000.0) # every half year
|
|
554
|
+
# pr = set_output_times(pr, 31558000.0) # every year
|
|
555
|
+
|
|
556
|
+
# pr.grid = ns.grid
|
|
557
|
+
# pr.clear_generators()
|
|
558
|
+
# for g in ns.generatorlist:
|
|
559
|
+
# pr.add_generator(g)
|
|
560
|
+
# # Append all additinal generators at the end
|
|
561
|
+
# gs_to_add = read_gener_file('production.geners')
|
|
562
|
+
# for g in gs_to_add:
|
|
563
|
+
# pr.add_generator(g)
|
|
564
|
+
|
|
565
|
+
# pr.write("real_model_pr.dat", echo_extra_precision=True)
|
|
566
|
+
# sav.write("real_model_pr.incon", reset=True)
|
|
567
|
+
|
|
568
|
+
# print('Running PR ...')
|
|
569
|
+
# START_TIME = time.time()
|
|
570
|
+
# pr.run(simulator=simulator, silent=silent)
|
|
571
|
+
# print('PR finished after ', (time.time() - START_TIME), 'seconds')
|
|
572
|
+
|
|
573
|
+
# prsav = t2incon("real_model_pr.save")
|
|
574
|
+
# if abs(prsav.timing['sumtim'] - target_pr_time) > 1000:
|
|
575
|
+
# print('Warning PR ends at %e sec, did not reach target time: %e' % (float(prsav.timing['sumtim']), float(target_pr_time)))
|
|
576
|
+
# print(''.join([line for line in tail('real_model_pr.listing', n=20)]))
|
|
577
|
+
|
|
578
|
+
return True
|
|
579
|
+
|
|
580
|
+
def get_t2():
|
|
581
|
+
with open('_tough2', 'r') as f:
|
|
582
|
+
line = f.readlines()[0].strip()
|
|
583
|
+
return line
|
|
584
|
+
|
|
585
|
+
def run_ns_pr():
|
|
586
|
+
""" call this from pest_model.py """
|
|
587
|
+
if config['simulator']['input-type'] == 'waiwera':
|
|
588
|
+
return run_ns_pr_waiwera(skippr=config['model']['skip-pr'],
|
|
589
|
+
sav2inc=True,
|
|
590
|
+
simulator=config['simulator']['executable'],
|
|
591
|
+
allow_failed_ns=True,
|
|
592
|
+
silent=False)
|
|
593
|
+
elif config['simulator']['input-type'] == 'aut2':
|
|
594
|
+
return run_ns_pr_aut2(skippr=config['model']['skip-pr'],
|
|
595
|
+
sav2inc=False,
|
|
596
|
+
simulator=config['simulator']['executable'],
|
|
597
|
+
allow_failed_ns=True,
|
|
598
|
+
silent=False)
|
|
599
|
+
else:
|
|
600
|
+
raise NotImplementedError('No implementation of run_ns_pr() for input-type: ' + config['simulator']['input-type'])
|
|
601
|
+
|
|
602
|
+
def main_cli(argv=[]):
|
|
603
|
+
skippr = config['model']['skip-pr']
|
|
604
|
+
sav2inc = False
|
|
605
|
+
|
|
606
|
+
if len(argv) > 1:
|
|
607
|
+
if '--skip-pr' in argv[1:]:
|
|
608
|
+
skippr = True
|
|
609
|
+
if '--sav2inc' in argv[1:]:
|
|
610
|
+
sav2inc = True
|
|
611
|
+
|
|
612
|
+
if config['simulator']['input-type'] == 'waiwera':
|
|
613
|
+
run_ns_pr_waiwera(skippr, sav2inc, simulator=get_t2(), silent=True)
|
|
614
|
+
else:
|
|
615
|
+
run_ns_pr_aut2(skippr=False, sav2inc=False,
|
|
616
|
+
simulator=config['simulator']['executable'],
|
|
617
|
+
allow_failed_ns=True, silent=True)
|