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/common.py ADDED
@@ -0,0 +1,194 @@
1
+ import os
2
+ import os.path
3
+ import string
4
+ import importlib.resources as resources
5
+ import shutil
6
+
7
+ # Access nested dictionary items via a list of keys
8
+ from functools import reduce # forward compatibility for Python 3
9
+ import operator
10
+
11
+ import tomlkit
12
+
13
+ def check_required(finput, name, fdefault=None):
14
+ if not os.path.isfile(finput):
15
+ print("\nWarning! %s file '%s' is not found in current working directory:" % (name, finput))
16
+ print(" %s\n" % os.getcwd())
17
+ ans = input('Do you want goPEST to create a default file? (y/n) ')
18
+ if 'y' in ans.lower():
19
+ if fdefault is None:
20
+ fdefault = finput
21
+ default_finput = resources.files('gopest.data') / fdefault
22
+ with resources.as_file(default_finput) as f:
23
+ shutil.copyfile(f, finput)
24
+ print("Default %s file '%s' created, please review and re-run " \
25
+ "command 'gopest init'." % (name, finput))
26
+ exit(0)
27
+ else:
28
+ print("Error! File '%s' is required for goPEST to work." % finput)
29
+ print('Existing...')
30
+ exit(1)
31
+
32
+
33
+ check_required('goPESTconfig.toml', 'Configuration')
34
+
35
+ """ this allows gopest.common.config to be used directly, eg.
36
+ from gopest.common import config as cfg
37
+ print(cfg['pest']['executable'])
38
+ print(cfg['simulator']['executable'])
39
+ """
40
+ with open('goPESTconfig.toml', 'r') as f:
41
+ config = tomlkit.load(f)
42
+
43
+ if 'silent_slaves' not in config['pest']:
44
+ config['pest']['silent_slaves'] = True
45
+
46
+ """ this allows gopest.common.runtime to be used directly, eg.
47
+ from gopest.common import runtime
48
+ print(runtime['filename']['fincon'])
49
+ print(runtime['filename']['fdatns'])
50
+ """
51
+ runtime = {}
52
+ def runtime_filenames(check=False):
53
+ """ work out filenames for all internal model files """
54
+ def getext(fn): return os.path.splitext(fn)[1].lower()
55
+ all_geoms = ['g_real_model' + getext(f) for f in config['model']['original']['geometry-files']]
56
+ input_typ = config['simulator']['input-type']
57
+ output_typ = config['simulator']['output-type']
58
+ sequence = config['model']['sequence']
59
+ if input_typ == 'aut2':
60
+ fsave = 'real_model_' + sequence[0] + '.save'
61
+ fincon = 'real_model_' + 'incon' + '.incon'
62
+ fdato = 'real_model_' + 'original' + '.dat'
63
+ fdats = ['real_model_' + seq + '.dat' for seq in sequence]
64
+ fincs = ['real_model_' + seq + '.incon' for seq in sequence]
65
+ fsavs = ['real_model_' + seq + '.save' for seq in sequence]
66
+ if output_typ == 'h5':
67
+ flsts = ['real_model_' + seq + '.h5' for seq in sequence]
68
+ else:
69
+ flsts = ['real_model_' + seq + '.listing' for seq in sequence]
70
+ elif input_typ == 'waiwera':
71
+ fsave = 'real_model_' + sequence[0] + '.h5'
72
+ fincon = 'real_model_' + 'incon' + '.h5'
73
+ fdato = 'real_model_' + 'original' + '.json'
74
+ fdats = ['real_model_' + seq + '.json' for seq in sequence]
75
+ flsts = ['real_model_' + seq + '.h5' for seq in sequence]
76
+ fincs = ['real_model_' + seq + '_inc.h5' for seq in sequence]
77
+ fsavs = ['real_model_' + seq + '.h5' for seq in sequence]
78
+ filenames = {
79
+ # single string properties
80
+ 'geom': 'g_real_model.dat',
81
+ 'save': fsave,
82
+ 'incon': fincon,
83
+ 'dat_orig': fdato,
84
+ # following peoperties are lists
85
+ 'all_geoms': all_geoms,
86
+ 'dat_seq': fdats,
87
+ 'lst_seq': flsts,
88
+ 'inc_seq': fincs,
89
+ 'sav_seq': fsavs,
90
+ }
91
+ if check:
92
+ for k,fnames in filenames.items():
93
+ if not isinstance(fnames, list):
94
+ fnames = [fnames]
95
+ for fn in fnames:
96
+ if not os.path.exists(fn):
97
+ raise Exception('Cannot find file %s in the working dir.' % fn)
98
+ return filenames
99
+ runtime['filename'] = runtime_filenames()
100
+
101
+ ########## utility classes and functions
102
+ class TwoWayDict(dict):
103
+ def __init__(self,copyFrom=None):
104
+ if copyFrom is not None:
105
+ for k in copyFrom.keys():
106
+ self[k] = copyFrom[k]
107
+ def __len__(self):
108
+ return dict.__len__(self) / 2
109
+ def __setitem__(self, key, value):
110
+ if key in self: raise Exception('TwoWayDict repeated key: %s' % str(key))
111
+ dict.__setitem__(self, key, value)
112
+ if value in self: raise Exception('TwoWayDict repeated key: %s' % str(value))
113
+ dict.__setitem__(self, value, key)
114
+
115
+ class Singleton(object):
116
+ __single = None # the one, true Singleton
117
+ def __new__(classtype, *args, **kwargs):
118
+ # Check to see if a __single exists already for this class
119
+ # Compare class types instead of just looking for None so
120
+ # that subclasses will create their own __single objects
121
+ if classtype != type(classtype.__single):
122
+ classtype.__single = object.__new__(classtype, *args, **kwargs)
123
+ return classtype.__single
124
+
125
+ def readList(f):
126
+ """ reads a file and returns a list of entries, an entry is a list strings
127
+ all lines starts with '#' are ignored """
128
+ entryName, entries = [], []
129
+ for line in f.readlines():
130
+ if len(line.strip()) == 0: continue # empty lines
131
+ if line.strip()[0] == '#': continue # comment lines
132
+ if line.strip()[0] == '[': # [something] item opening
133
+ tmp = line.strip()
134
+ ikeyend=tmp.find(']')
135
+ keyword=tmp[1:ikeyend]
136
+ if keyword=='END': break # [END] finishes all
137
+ entryName.append(keyword)
138
+ entries.append([])
139
+ continue
140
+ # all other non-empty lines parts of last entry (until [END])
141
+ # error if some non-comment line apear above first keyword
142
+ entries[-1].append(line)
143
+ return (entryName, entries)
144
+
145
+ def updateDict(dic,lines):
146
+ """ evaluate lines and update the content of the argument dictionary. A KeyError
147
+ exception is raised if the key from lines is not in dic. Each line in lines
148
+ is a simple string like 'key = val'. """
149
+ keys,vals = [],[]
150
+ for line in lines:
151
+ if line.count('=') != 1: raise Exception
152
+ k,v = line.split('=')
153
+ if k.strip() not in dic:
154
+ print(dic.keys())
155
+ raise KeyError
156
+ dic[k.strip()] = eval(v)
157
+ return dic
158
+
159
+ def merge_dols(dol1, dol2):
160
+ """ merging dicts of lists into a new dict of lists. """
161
+ keys = set(dol1).union(dol2)
162
+ no = []
163
+ return dict((k, dol1.get(k, no) + dol2.get(k, no)) for k in keys)
164
+
165
+ def updateObj(obj,lines):
166
+ """ evaluate lines and modify the members of the argument object, A KeyError
167
+ exception is raised if the key from lines is not a member of the object.
168
+ Each line in lines is a simple string like 'key = val'. """
169
+ keys,vals = [],[]
170
+ for line in lines:
171
+ if line.count('=') != 1: raise Exception
172
+ k,v = line.split('=')
173
+ # if k.strip() not in obj.__dict__.keys():
174
+ # print(k, ' not supported, try: ', obj.__dict__.keys())
175
+ # raise KeyError
176
+ setattr(obj,k.strip(),eval(v))
177
+ return obj
178
+
179
+ def private_cleanup_name(s):
180
+ """ cleans up string so no space, no funny symbols. it will remove all
181
+ punctuations chars apart from those specified in rep, which will be '_' """
182
+ rep = ' .*'
183
+ rmv = string.punctuation
184
+ for c in rep: rmv = rmv.replace(c,'_')
185
+ for c in rmv: s = s.replace(c,'')
186
+ for c in rep: s = s.replace(c,'_')
187
+ return s
188
+
189
+ def getFromDict(dataDict, mapList):
190
+ return reduce(operator.getitem, mapList, dataDict)
191
+
192
+ def setInDict(dataDict, mapList, value):
193
+ getFromDict(dataDict, mapList[:-1])[mapList[-1]] = value
194
+
gopest/data/case.pst ADDED
@@ -0,0 +1,67 @@
1
+ pcf
2
+ * control data
3
+ restart estimation
4
+ 4 16 8 0 7
5
+ 1 1 single point 1 0 0
6
+ 10.0 -20.0 0.3 0.03 -100 0 run_slow_fac=20.0 lamforgive derforgive
7
+ 10.0 10.0 0.001
8
+ 0.1 5 noaui
9
+ 0 0.005 4 4 0.005 4
10
+ 1 1 1 jcosaveitn parsaveitn rrfsave
11
+ * singular value decomposition
12
+ 1
13
+ 3249 5.0e-7
14
+ 0
15
+ * parameter groups
16
+ k1 relative 0.01 0.0 switch 2.0 parabolic
17
+ k2 relative 0.01 0.0 switch 2.0 parabolic
18
+ k3 relative 0.01 0.0 switch 2.0 parabolic
19
+ upflow relative 0.01 0.0 switch 2.0 parabolic
20
+ por relative 0.03 0.0 switch 2.0 parabolic
21
+ rech relative 0.05 0.0 switch 2.0 parabolic
22
+ heat relative 0.01 0.0 switch 2.0 parabolic
23
+ rpcap relative 0.05 0.0 switch 2.0 parabolic
24
+ * parameter data
25
+ R1upper log factor 5e-15 1e-17 4.5e-12 k1 1.0 0.0 1
26
+ R2upper log factor 5e-15 1e-17 4.5e-12 k2 1.0 0.0 1
27
+ R3upper log factor 5e-15 1e-17 3e-12 k3 1.0 0.0 1
28
+ RPupper log factor 0.15 0.01 0.5 por 1.0 0.0 1
29
+ * observation groups
30
+ temp
31
+ enth
32
+ press
33
+ time
34
+ enth_g
35
+ vpress
36
+ boilp
37
+ * observation data
38
+ tt_GGL_1_0001 1.4320198019802e+02 3.50000e-02 temp
39
+ tt_GGL_1_0002 1.6236329113924e+02 3.50000e-02 temp
40
+ tt_GGL_1_0003 1.6844148148148e+02 3.50000e-02 temp
41
+ tt_GGL_1_0004 1.9702444444444e+02 3.50000e-02 temp
42
+ tt_GGL_1_0005 2.0340636942675e+02 3.50000e-02 temp
43
+ tt_GGL_1_0006 1.8860000000000e+02 3.50000e-02 temp
44
+ tt_GGL_1_0007 1.8903172147002e+02 3.50000e-02 temp
45
+ tt_GGL_1_0008 1.9153636363636e+02 3.50000e-02 temp
46
+ tt_GGL_1_0009 1.9463612565445e+02 3.50000e-02 temp
47
+ tt_GGL_1_0010 1.7681111111111e+02 3.50000e-02 temp
48
+ tt_GGL_1_0011 1.8117493036212e+02 3.50000e-02 temp
49
+ tt_GGL_1_0012 1.9303333333333e+02 3.50000e-02 temp
50
+ tt_GGL_1_0013 2.0483466042155e+02 3.50000e-02 temp
51
+ tt_GGL_1_0014 2.1203960396040e+02 3.50000e-02 temp
52
+ tt_GGL_1_0015 2.1337673267327e+02 3.50000e-02 temp
53
+ tt_GGL_1_0016 2.0401980198020e+02 3.50000e-02 temp
54
+ * model command line
55
+ gopest run-pest-model
56
+ * model input/output
57
+ pest_model.tpl pest_model.dat
58
+ pest_model.ins pest_model.obf
59
+ * prior information
60
+ * distribution files
61
+ 2 real_model_ns.save real_model_incon.incon real_model_incon.incon real_model_incon.incon
62
+ 1 real_model_ns.save real_model_incon.incon.999
63
+ 1 real_model_ns.dat real_model_ns.dat.999
64
+ 1 real_model_pr.h5 real_model_pr.h5.999
65
+ 1 pest_model.dat pest_model.dat.999
66
+ command = "gopest save-iter-model"
67
+ # end
@@ -0,0 +1,95 @@
1
+ # This is goPEST's main configuration file.
2
+
3
+ [pest]
4
+ mode = 'local'
5
+ dir = ""
6
+ executable = "pest_hp"
7
+ executable_agent = "agent_hp"
8
+ port = "24001"
9
+ num_slaves = 2
10
+ slave_dirs = ""
11
+
12
+ case-name = 'case'
13
+ switches = []
14
+ # additional swiches for beopest, eg /s for restart, /p1 for parallise 1st model run
15
+ # should not use /p1 with svda, no /p1 with obsreref_10 either
16
+ # /hpstart, make sure PST_NAME.hp exists
17
+ # /i jco reuse, make sure PST_NAME.jco exists
18
+ # NOTE it's possible to use /hpstart and /i together, will start update tests right away
19
+ # NOTE working directory is assumed to be where this script is launched
20
+
21
+ [model]
22
+ skip = true # skips actual simulation, existing model output is used
23
+ skip-pr = true
24
+ silent = true
25
+ sequence = ['ns', 'pr']
26
+
27
+ [model.original]
28
+ # these original model files will be renamed to goPEST's internal convention,
29
+ # which is usually something like real_model_xx, where xx is the sequence name.
30
+
31
+ # specify at least Mulgrid geometry file here, needs .msh etc if running Waiwera
32
+ geometry-files = ['raw/gair_smodel.dat', 'raw/gair_smodel.msh']
33
+ incon-file = 'raw/air_smodel_ns.incon'
34
+ ns-input-file = 'raw/air_smodel_ns.dat'
35
+ pr-input-file = 'raw/air_smodel_pr.dat'
36
+
37
+ # optional original output file, useful for debug
38
+ ns-output-file = 'raw/air_smodel_ns.h5'
39
+ pr-output-file = 'raw/air_smodel_pr.h5'
40
+
41
+ [simulator]
42
+ input-type = "aut2" # "waiwera" or "aut2"
43
+ output-type = "h5" # "listing" or "h5", will always be "h5" if input-type = "waiwera"
44
+
45
+ executable = 'AUTOUGH2_7_1-7.exe'
46
+
47
+ # these will be attached to the end of simulation command (useful for waiwera)
48
+ cmd-options = []
49
+
50
+ [nesi]
51
+ project = "uoa00123"
52
+ cluster_master = "mahuika"
53
+ cluster_forward = "maui"
54
+ walltime_master = "72:00:00" # hour:min:sec
55
+ walltime_forward = "12:00:00" # hour:min:sec
56
+ ntasks = 40
57
+
58
+ [nesi.maui]
59
+ project = "uoa00123"
60
+ walltime_forward = "12:00:00" # hour:min:sec
61
+ ntasks = 40
62
+ env_init = [
63
+ "module swap PrgEnv-cray PrgEnv-gnu",
64
+ "module swap gcc gcc/8.3.0",
65
+ "module load cray-python",
66
+ "export HDF5_USE_FILE_LOCKING=FALSE", # avoids h5py unable to lock file (Maui only)
67
+ "export PYTHONPATH=/nesi/project/uoa00124/pytough:/nesi/project/uoa00124/utils:/nesi/project/uoa00124/software/py27-maui/:$PYTHONPATH",
68
+ "printenv PYTHONPATH",
69
+ ]
70
+
71
+ [nesi.mahuika]
72
+ project = "uoa00123"
73
+ walltime_forward = "24:00:00" # hour:min:sec
74
+ ntasks = 40
75
+ env_init = [
76
+ "module load gimkl/2018b",
77
+ ]
78
+
79
+ [files]
80
+ # all files required by a PEST slave and forward model run:
81
+ slave = [
82
+ "g_real_model.dat",
83
+ "g_real_model.msh",
84
+ "real_model_original.json",
85
+ "real_model.incon.h5",
86
+ # observation data files
87
+ "data.json",
88
+ # these are for forward run
89
+ "gs_production.json",
90
+ "real_model_pr.output.json",
91
+ "real_model_pr.time.json",
92
+ ]
93
+ # additional files required by PEST master
94
+ master = []
95
+
@@ -0,0 +1,94 @@
1
+ # This is goPEST's main configuration file.
2
+
3
+ [pest]
4
+ dir = ""
5
+ executable = "pest_hp"
6
+ executable_agent = "agent_hp"
7
+ port = "24001"
8
+ num_slaves = 1
9
+ slave_dirs = ""
10
+
11
+ case-name = 'case'
12
+ switches = []
13
+ # additional swiches for beopest, eg /s for restart, /p1 for parallise 1st model run
14
+ # should not use /p1 with svda, no /p1 with obsreref_10 either
15
+ # /hpstart, make sure PST_NAME.hp exists
16
+ # /i jco reuse, make sure PST_NAME.jco exists
17
+ # NOTE it's possible to use /hpstart and /i together, will start update tests right away
18
+ # NOTE working directory is assumed to be where this script is launched
19
+
20
+ [model]
21
+ skip = true # skips actual simulation, existing model output is used
22
+ skip-pr = true
23
+ silent = true
24
+ sequence = ['ns', 'pr']
25
+
26
+ [model.original]
27
+ # these original model files will be renamed to goPEST's internal convention,
28
+ # which is usually something like real_model_xx, where xx is the sequence name.
29
+
30
+ # specify at least Mulgrid geometry file here, needs .msh etc if running Waiwera
31
+ geometry-files = ['raw/gair_smodel.dat', 'raw/gair_smodel.msh']
32
+ incon-file = 'raw/air_smodel_ns.incon'
33
+ ns-input-file = 'raw/air_smodel_ns.dat'
34
+ pr-input-file = 'raw/air_smodel_pr.dat'
35
+
36
+ # optional original output file, useful for debug
37
+ ns-output-file = 'raw/air_smodel_ns.h5'
38
+ pr-output-file = 'raw/air_smodel_pr.h5'
39
+
40
+ [simulator]
41
+ input-type = "aut2" # "waiwera" or "aut2"
42
+ output-type = "h5" # "listing" or "h5", will always be "h5" if input-type = "waiwera"
43
+
44
+ executable = 'AUTOUGH2_7_1-7.exe'
45
+
46
+ # these will be attached to the end of simulation command (useful for waiwera)
47
+ cmd-options = []
48
+
49
+ [nesi]
50
+ project = "uoa00123"
51
+ cluster_master = "mahuika"
52
+ cluster_forward = "maui"
53
+ walltime_master = "72:00:00" # hour:min:sec
54
+ walltime_forward = "12:00:00" # hour:min:sec
55
+ ntasks = 40
56
+
57
+ [nesi.maui]
58
+ project = "uoa00123"
59
+ walltime_forward = "12:00:00" # hour:min:sec
60
+ ntasks = 40
61
+ env_init = [
62
+ "module swap PrgEnv-cray PrgEnv-gnu",
63
+ "module swap gcc gcc/8.3.0",
64
+ "module load cray-python",
65
+ "export HDF5_USE_FILE_LOCKING=FALSE", # avoids h5py unable to lock file (Maui only)
66
+ "export PYTHONPATH=/nesi/project/uoa00124/pytough:/nesi/project/uoa00124/utils:/nesi/project/uoa00124/software/py27-maui/:$PYTHONPATH",
67
+ "printenv PYTHONPATH",
68
+ ]
69
+
70
+ [nesi.mahuika]
71
+ project = "uoa00123"
72
+ walltime_forward = "24:00:00" # hour:min:sec
73
+ ntasks = 40
74
+ env_init = [
75
+ "module load gimkl/2018b",
76
+ ]
77
+
78
+ [files]
79
+ # all files required by a PEST slave and forward model run:
80
+ slave = [
81
+ "g_real_model.dat",
82
+ "g_real_model.msh",
83
+ "real_model_original.json",
84
+ "real_model.incon.h5",
85
+ # observation data files
86
+ "data.json",
87
+ # these are for forward run
88
+ "gs_production.json",
89
+ "real_model_pr.output.json",
90
+ "real_model_pr.time.json",
91
+ ]
92
+ # additional files required by PEST master
93
+ master = []
94
+