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/par.py ADDED
@@ -0,0 +1,332 @@
1
+ import json
2
+ from os.path import splitext, basename, isfile
3
+ import inspect
4
+ import functools
5
+ from collections import OrderedDict
6
+
7
+ from t2data import *
8
+
9
+ from gopest.common import TwoWayDict
10
+ from gopest.common import Singleton
11
+ from gopest.common import readList
12
+ from gopest.common import updateObj
13
+ from gopest.common import private_cleanup_name
14
+
15
+ # implementation:
16
+ # a user entry is something simple a user can undersand and easily enter
17
+ # these are entered as groups, each with type and settings. these are
18
+ # turned into what PEST requires.
19
+ #
20
+
21
+ # i need a dictionary, leys of parameter data type (short), which maps to
22
+ # functions from the user defined functions that can modify t2data objects
23
+
24
+ from gopest.common import config as cfg
25
+ INPUT_TYPE = cfg['simulator']['input-type']
26
+
27
+ from gopest import par_def
28
+ par_classes = {}
29
+ for n,c in inspect.getmembers(par_def, inspect.isclass):
30
+ if issubclass(c, par_def.ParDef):
31
+ par_classes[n] = c
32
+
33
+ class PestParamGroups(object):
34
+ """ representation of entries in PEST * parameter groups """
35
+ def __init__(self,name,INCTYP='relative',DERINC=0.01,DERINCLB=0.0,
36
+ FORCEN='switch',DERINCMUL=2.0,DERMTHD='parabolic'):
37
+ self.PARGPNME = name
38
+ self.INCTYP = INCTYP
39
+ self.DERINC=DERINC
40
+ self.DERINCLB=DERINCLB
41
+ self.FORCEN=FORCEN
42
+ self.DERINCMUL=DERINCMUL
43
+ self.DERMTHD=DERINCMUL
44
+
45
+ self.defPARLBND = 0.0
46
+ self.defPARUBND = 0.0
47
+
48
+ class PestParamData(object):
49
+ """ this is equalivalent to each of * parameter data in PEST. it is
50
+ able to write entries for PEST control file (.pst), and PEST template
51
+ file (.tpl). It is also responsible of reading PEST generated 'model'
52
+ file and make real changes into Tough2 input file """
53
+ #? do I have too many tasks for this class?
54
+ def __init__(self,name='',PARTRANS='none',PARCHGLIM='factor',PARVAL1=1.0,
55
+ PARLBND=0.5,PARUBND=1.5,PARGP='grp',SCALE=1.0,OFFSET=0.0,DERCOM=1,
56
+ TEMPLATEWIDTH=7):
57
+ self.PARNME = name
58
+ self.PARTRANS=PARTRANS
59
+ self.PARCHGLIM=PARCHGLIM
60
+ self.PARVAL1=PARVAL1
61
+ self.PARLBND=PARLBND
62
+ self.PARUBND=PARUBND
63
+ self.PARGP=PARGP
64
+ self.SCALE=SCALE
65
+ self.OFFSET=OFFSET
66
+ self.DERCOM=DERCOM
67
+
68
+ # this is not part of PEST's design, used by goPEST to determine the
69
+ # correct template field width, which is related to the precision of
70
+ # TOUGH2 input. It should be 7 for a standard TOUGH2 entry, with 2
71
+ # less for starting- and ending-mark, and one less because PEST has
72
+ # better ability to squeeze one extra precision than Python using the
73
+ # same width. If using .pdat, you should probably use 12 (15-3) to get
74
+ # the precision effect.
75
+ self.TEMPLATEWIDTH = TEMPLATEWIDTH
76
+
77
+ def write(self, f=None):
78
+ """ expects f to be a file object ready to write(), otherwise print to screen """
79
+ line = ' '.join([str(a) for a in [
80
+ self.PARNME,
81
+ self.PARTRANS,
82
+ self.PARCHGLIM,
83
+ self.PARVAL1,
84
+ self.PARLBND,
85
+ self.PARUBND,
86
+ self.PARGP,
87
+ self.SCALE,
88
+ self.OFFSET,
89
+ self.DERCOM,
90
+ ]])
91
+ if f is None:
92
+ print(line)
93
+ else:
94
+ f.write(line + '\n')
95
+
96
+
97
+ PARAM_ALIAS = TwoWayDict(par_def.shortNames)
98
+
99
+ class PestParamDataName(Singleton):
100
+ """ remembers a list of parameter data and observation data """
101
+ def __init__(self):
102
+ self.names = set([])
103
+ def newName(self,basename):
104
+ apnd = ' 01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
105
+ i = 0
106
+ newname = (basename + apnd[i]).strip()
107
+ while newname in self.names:
108
+ i += 1
109
+ if i >= len(apnd):
110
+ raise Exception('Unable to find unused parameter name for:' + basename)
111
+ break
112
+ newname = (basename + apnd[i]).strip()
113
+ return newname
114
+ def add(self,newname):
115
+ self.names.add(newname)
116
+
117
+ class UserEntryParam(object):
118
+ """ understands user entry group and its setings, type. and will be
119
+ responsible of creating PestParamData objects, as each * parameter data
120
+ in PEST """
121
+ ListType = ['ForEach','SingleValue','TiedValues']
122
+ def __init__(self, paramListType, paramList, t2objListType, t2objList, t2objType,
123
+ dat, defaults=None):
124
+ # paramListType 'ForEach' or 'SingleValue' or 'TiedValues'
125
+ # paramList a list of 'permeability_1' or 'porosity' etc
126
+ # t2objListType 'ForEach' or 'SingleValue' or 'TiedValues'
127
+ # t2objList a list of PyTOUGH objects names 'aaa15' or 'BA***' etc
128
+ # t2objType one of 'Rocktype', 'Element', or 'Generator'
129
+ # defaults dict of default PestParamData of each PARAM_TYPE
130
+ if paramListType not in self.ListType: raise Exception(paramListType, ' is not in ', ListType)
131
+ if t2objListType not in self.ListType: raise Exception(t2objListType, ' is not in ', ListType)
132
+ for p in [p for p in paramList if p not in par_classes]: raise Exception(p, ' is not valid')
133
+ self.t2objList = t2objList
134
+ self.t2objType = t2objType
135
+ self.paramListType=paramListType
136
+ self.paramList=paramList
137
+ self.t2objListType=t2objListType
138
+ from copy import deepcopy
139
+ self.defaults=deepcopy(defaults)
140
+
141
+ # generate these by calling makeParamDataNames, pest * parameter data entries
142
+ self.paramData = None
143
+ self.ties = None
144
+
145
+ def makeParamData(self,dat,tpl):
146
+ """ generate a list of paramData and write to PEST template file"""
147
+ # ??? Maybe I should make it spit tpl file entries, instead of write directly into file?
148
+ if (self.paramData is not None) and (self.ties is not None): return
149
+ self.paramData = []
150
+ self.ties = []
151
+
152
+ # reuse ParDef instances (used as getter/setter here) for param type
153
+ par_getters = {}
154
+ for pt in self.paramList:
155
+ if pt not in par_getters:
156
+ par_getters[pt] = par_classes[pt](INPUT_TYPE)
157
+
158
+ # obtain a list of names that exists in all self.paramList and self.t2objList
159
+ # use OrderedDict as an ordered set, to remember order (ordr is noce to have)
160
+ names = []
161
+ intersect = None
162
+ for pt in self.paramList:
163
+ for pattern in self.t2objList:
164
+ a = par_getters[pt].find_names(dat, pattern)
165
+ names += a
166
+ if intersect is None:
167
+ intersect = set(a)
168
+ else:
169
+ intersect = intersect & set(a)
170
+ name_order = OrderedDict.fromkeys(names).keys()
171
+ matchedList = [n for n in name_order if n in intersect]
172
+
173
+ # if both ForEach
174
+ for t2o in matchedList:
175
+ for pt in self.paramList:
176
+ if (pt in self.defaults) and (len(self.defaults[pt].PARNME) == 2):
177
+ # if set properly already (len=2), use the specified value
178
+ if isinstance(t2o, tuple):
179
+ nname = PestParamDataName().newName(self.defaults[pt].PARNME + private_cleanup_name(t2o[-1][:5]))
180
+ else:
181
+ nname = PestParamDataName().newName(self.defaults[pt].PARNME + private_cleanup_name(t2o))
182
+ else:
183
+ # use PARAM_ALIAS as name base if not set properly
184
+ if isinstance(t2o, tuple):
185
+ nname = PestParamDataName().newName(PARAM_ALIAS[pt] + private_cleanup_name(t2o[-1][:5]))
186
+ else:
187
+ nname = PestParamDataName().newName(PARAM_ALIAS[pt] + private_cleanup_name(t2o))
188
+ PestParamDataName().add(nname)
189
+ if self.defaults is not None:
190
+ if pt in self.defaults:
191
+ from copy import deepcopy
192
+ pd = deepcopy(self.defaults[pt])
193
+ else:
194
+ pd = PestParamData()
195
+ else:
196
+ pd = PestParamData()
197
+ pd.PARNME = nname
198
+ pd.PARVAL1 = par_getters[pt].get(dat, t2o)
199
+ self.paramData.append(pd)
200
+ theline = "$%-" + str(pd.TEMPLATEWIDTH) + 's$, %-20s, "%s"\n'
201
+ tpl.write(theline % (nname, ('"%s"' % pt), str([t2o])))
202
+
203
+ def readUserParameter(userListName, dat):
204
+ """ returns a list of UserEntryParam from reading the file with name
205
+ userListName """
206
+ userEntries = []
207
+ with open(userListName,'r') as f:
208
+ entryName, entry = readList(f)
209
+ # some defaults even if no sections exists:
210
+ parDefaults = {}
211
+ for i,en in enumerate(entryName):
212
+ if en == 'Defaults':
213
+ for line in entry[i]:
214
+ if ':' in line:
215
+ ptype = [s.strip() for s in line.split(':')[0].split(',')]
216
+ for p in ptype:
217
+ if p not in parDefaults: parDefaults[p] = PestParamData()
218
+ else:
219
+ for p in ptype:
220
+ updateObj(parDefaults[p],[line])
221
+ if en == 'Param':
222
+ if len(entry[i]) < 2: raise Exception
223
+ tmp1, tmp2 = entry[i][0].split(':')
224
+ paramListType = tmp1.strip()
225
+ paramList = [s.strip() for s in tmp2.split(',')]
226
+ tmp1, tmp2 = entry[i][1].split(':')
227
+ t2objListType = tmp1.strip()
228
+ t2objType = tmp2.strip()
229
+ t2objList = []
230
+ for line in entry[i][2:]:
231
+ t2objList.append(eval(line))
232
+ userEntries.append(UserEntryParam(paramListType,paramList,
233
+ t2objListType,t2objList,t2objType,dat,parDefaults))
234
+ return userEntries
235
+
236
+ def load_model_config(dat):
237
+ """ Return config dict loaded from .json file with same model base name.
238
+ """
239
+ jname = splitext(dat.filename)[0] + '.json'
240
+ # print("*****", jname)
241
+ if isfile(jname):
242
+ with open(jname, 'rU') as jf:
243
+ return json.load(jf)
244
+ else:
245
+ return {}
246
+
247
+ def save_model_config(dat, config):
248
+ """ Saves config (dict) object into .json using same basename as t2data.
249
+ """
250
+ jname = splitext(dat.filename)[0] + '.json'
251
+ with open(jname, 'w') as jf:
252
+ json.dump(config, jf, indent=4)
253
+
254
+ def generate_params_and_tpl(origInput, tplToWrite, par_data):
255
+ """ this reads goPESTpar.list and generate appropriate template file and
256
+ writes * parameter data lines into a file """
257
+ if INPUT_TYPE == 'aut2':
258
+ dat = t2data(origInput)
259
+ dat.config = load_model_config(dat)
260
+ elif INPUT_TYPE == 'waiwera':
261
+ with open(origInput, 'r') as f:
262
+ dat = json.load(f)
263
+ else:
264
+ raise Exception()
265
+
266
+ uentry = readUserParameter('goPESTpar.list', dat)
267
+
268
+ if par_data is not None:
269
+ parf = open(par_data, 'w')
270
+ else:
271
+ parf = None
272
+ tpl = open(tplToWrite, 'w')
273
+ tpl.write('ptf $\n')
274
+ for up in uentry:
275
+ up.makeParamData(dat,tpl)
276
+ for pp in up.paramData:
277
+ pp.write(parf)
278
+ tpl.close()
279
+ if parf is not None:
280
+ parf.close()
281
+
282
+ def generate_real_model(origInput, pestModel, realInput):
283
+ """ this reads PEST generated model file and create the real TOUGH2 model
284
+ """
285
+ if INPUT_TYPE == 'aut2':
286
+ dat = t2data(origInput)
287
+ dat.config = load_model_config(dat)
288
+ elif INPUT_TYPE == 'waiwera':
289
+ with open(origInput, 'r') as f:
290
+ dat = json.load(f)
291
+ else:
292
+ raise Exception()
293
+
294
+ # reuse ParDef instances (used as getter/setter here) for param type
295
+ par_setters = {}
296
+
297
+ with open(pestModel,'r') as pmodel:
298
+ for line in pmodel.readlines():
299
+ vals = eval(line.strip())
300
+ pestValue, paramType, names = vals[0], vals[1], eval(vals[2])
301
+ if paramType not in par_setters:
302
+ par_setters[paramType] = par_classes[paramType](INPUT_TYPE)
303
+ par_setters[paramType].set(dat, names[0], pestValue)
304
+
305
+ if INPUT_TYPE == 'aut2':
306
+ dat.write(realInput, extra_precision=True, echo_extra_precision=True)
307
+ save_model_config(dat, dat.config)
308
+ elif INPUT_TYPE == 'waiwera':
309
+ with open(realInput, 'w') as f:
310
+ json.dump(dat, f, indent=4, sort_keys=True)
311
+
312
+ def goPESTpar(argv=[]):
313
+ userlistname = 'goPESTpar.list'
314
+
315
+ if len(argv) not in [3,4]:
316
+ print('to generate PEST .pst sections and .tpl (for once): ')
317
+ print(' gopest par origINPUT newPESTtpl')
318
+ print('to read PEST generated model file and create real INPUT for Tough2 (for each PEST forward run):')
319
+ print(' gopest par origINPUT pestINPUT realINPUT')
320
+
321
+ if len(argv) == 3:
322
+ origInput = argv[1]
323
+ tplToWrite = argv[2]
324
+ # write *param data lines to screen
325
+ generate_params_and_tpl(origInput, tplToWrite, None)
326
+
327
+ if len(argv) == 4:
328
+ origInput = argv[1]
329
+ pestModel = argv[2]
330
+ realInput = argv[3]
331
+
332
+ generate_real_model(origInput, pestModel, realInput)
gopest/par_def.py ADDED
@@ -0,0 +1,313 @@
1
+ """Definition file for parameter data types"""
2
+ #
3
+ # each function must accept three params: name,dat,val
4
+ # names: t2data object names, eg. block, gener etc, must be a list
5
+ # dat: your normal t2data object from PyTOUGH
6
+ # val: a number that is going to be assigned, when not exist value
7
+ # from dat will be returned, the first in the name list is used
8
+ #
9
+ # use existing entries as example to write new ones
10
+ # your new function name can then be used as 'param_type'
11
+ #
12
+ # the shortNames needs to be filled in, the right hand side
13
+ # string must be EXACTLY 3 characters wide, and NO SPACE
14
+ # these short names will be used as part of names in * parameter data
15
+ #
16
+
17
+ # TODO: consider using munch to allow access dictionary with object-oriented
18
+ # style? see:
19
+ # https://github.com/Infinidat/munch
20
+ # https://stackoverflow.com/questions/1305532/how-to-convert-a-nested-python-dict-to-object
21
+
22
+ import re
23
+
24
+ from gopest.common import getFromDict, setInDict
25
+
26
+ class ParDef(object):
27
+ """ Base class for parameter, used to access model input parameters """
28
+ def __init__(self, simulator):
29
+ super(ParDef, self).__init__()
30
+ if simulator not in ['aut2', 'waiwera']:
31
+ raise Exception("simulator '%s' not supported." % simulator)
32
+ self.simulator = simulator
33
+
34
+ def get(self, dat, name):
35
+ _get = getattr(self, 'get_' + self.simulator)
36
+ return _get(dat, name)
37
+ def get_aut2(self, dat, name):
38
+ raise NotImplementedError(self.__class__.__name__)
39
+ def get_waiwera(self, dat, name):
40
+ raise NotImplementedError(self.__class__.__name__)
41
+
42
+ def set(self, dat, name, value):
43
+ _set = getattr(self, 'set_' + self.simulator)
44
+ return _set(dat, name, value)
45
+ def set_aut2(self, dat, name, value):
46
+ raise NotImplementedError(self.__class__.__name__)
47
+ def set_waiwera(self, dat, name, value):
48
+ raise NotImplementedError(self.__class__.__name__)
49
+
50
+ def find_names(self, dat, pattern):
51
+ _find_names = getattr(self, 'find_names_' + self.simulator)
52
+ return _find_names(dat, pattern)
53
+ def find_names_aut2(self, dat, pattern):
54
+ raise NotImplementedError(self.__class__.__name__)
55
+ def find_names_waiwera(self, dat, pattern):
56
+ raise NotImplementedError(self.__class__.__name__)
57
+
58
+ class permeability_1_byrock(ParDef):
59
+ def get_aut2(self, dat, name):
60
+ return dat.grid.rocktype[name].permeability[0]
61
+
62
+ def set_aut2(self, dat, name, value):
63
+ dat.grid.rocktype[name].permeability[0] = value
64
+
65
+ def find_names_aut2(self, dat, pattern):
66
+ pattern = re.compile(pattern)
67
+ return [r.name for r in dat.grid.rocktypelist if pattern.match(r.name)]
68
+
69
+ def get_waiwera(self, dat, name):
70
+ for rock in dat['rock']['types']:
71
+ if rock['name'] == name:
72
+ return rock['permeability'][0]
73
+
74
+ def set_waiwera(self, dat, name, value):
75
+ for rock in dat['rock']['types']:
76
+ if rock['name'] == name:
77
+ rock['permeability'][0] = value
78
+
79
+ def find_names_waiwera(self, dat, pattern):
80
+ rex = re.compile(pattern)
81
+ return [r['name'] for r in dat['rock']['types'] if rex.match(r['name'])]
82
+
83
+ class permeability_2_byrock(ParDef):
84
+ def get_aut2(self, dat, name):
85
+ return dat.grid.rocktype[name].permeability[1]
86
+
87
+ def set_aut2(self, dat, name, value):
88
+ dat.grid.rocktype[name].permeability[1] = value
89
+
90
+ def find_names_aut2(self, dat, pattern):
91
+ pattern = re.compile(pattern)
92
+ return [r.name for r in dat.grid.rocktypelist if pattern.match(r.name)]
93
+
94
+ def get_waiwera(self, dat, name):
95
+ for rock in dat['rock']['types']:
96
+ if rock['name'] == name:
97
+ return rock['permeability'][1]
98
+
99
+ def set_waiwera(self, dat, name, value):
100
+ for rock in dat['rock']['types']:
101
+ if rock['name'] == name:
102
+ rock['permeability'][1] = value
103
+
104
+ def find_names_waiwera(self, dat, pattern):
105
+ rex = re.compile(pattern)
106
+ return [r['name'] for r in dat['rock']['types'] if rex.match(r['name'])]
107
+
108
+ class permeability_3_byrock(ParDef):
109
+ def get_aut2(self, dat, name):
110
+ return dat.grid.rocktype[name].permeability[2]
111
+
112
+ def set_aut2(self, dat, name, value):
113
+ dat.grid.rocktype[name].permeability[2] = value
114
+
115
+ def find_names_aut2(self, dat, pattern):
116
+ pattern = re.compile(pattern)
117
+ return [r.name for r in dat.grid.rocktypelist if pattern.match(r.name)]
118
+
119
+ def get_waiwera(self, dat, name):
120
+ for rock in dat['rock']['types']:
121
+ if rock['name'] == name:
122
+ return rock['permeability'][2]
123
+
124
+ def set_waiwera(self, dat, name, value):
125
+ for rock in dat['rock']['types']:
126
+ if rock['name'] == name:
127
+ rock['permeability'][2] = value
128
+
129
+ def find_names_waiwera(self, dat, pattern):
130
+ rex = re.compile(pattern)
131
+ return [r['name'] for r in dat['rock']['types'] if rex.match(r['name'])]
132
+
133
+ class porosity_byrock(ParDef):
134
+ def get_aut2(self, dat, name):
135
+ return dat.grid.rocktype[name].porosity
136
+
137
+ def set_aut2(self, dat, name, value):
138
+ dat.grid.rocktype[name].porosity = value
139
+
140
+ def find_names_aut2(self, dat, pattern):
141
+ pattern = re.compile(pattern)
142
+ return [r.name for r in dat.grid.rocktypelist if pattern.match(r.name)]
143
+
144
+ def get_waiwera(self, dat, name):
145
+ for rock in dat['rock']['types']:
146
+ if rock['name'] == name:
147
+ return rock['porosity']
148
+
149
+ def set_waiwera(self, dat, name, value):
150
+ for rock in dat['rock']['types']:
151
+ if rock['name'] == name:
152
+ rock['porosity'] = value
153
+
154
+ def find_names_waiwera(self, dat, pattern):
155
+ rex = re.compile(pattern)
156
+ return [r['name'] for r in dat['rock']['types'] if rex.match(r['name'])]
157
+
158
+ class massgener_rate(ParDef):
159
+ def get_aut2(self, dat, name):
160
+ for g in dat.generatorlist:
161
+ if g.name == name:
162
+ return g.gx
163
+
164
+ def set_aut2(self, dat, name, value):
165
+ for g in dat.generatorlist:
166
+ if g.name == name:
167
+ g.gx = value
168
+ return
169
+
170
+ def find_names_aut2(self, dat, pattern):
171
+ rex = re.compile(pattern)
172
+ return [g.name for g in dat.generatorlist if rex.match(g.name)]
173
+
174
+ def get_waiwera(self, dat, name):
175
+ for source in dat['source']:
176
+ if source['name'] == name:
177
+ return source['rate']
178
+
179
+ def set_waiwera(self, dat, name, value):
180
+ for source in dat['source']:
181
+ if source['name'] == name:
182
+ source['rate'] = value
183
+
184
+ def find_names_waiwera(self, dat, pattern):
185
+ rex = re.compile(pattern)
186
+ return [s['name'] for s in dat['source'] if rex.match(s['name'])]
187
+
188
+
189
+ class json_values(ParDef):
190
+ def get_aut2(self, dat, name):
191
+ """ expects name to be a tuple ([k1, k2, k3], last_key), where a list of
192
+ keys k1,k2,k3 (can use either str or int) leading up to just before the
193
+ last key.
194
+ """
195
+ cfg = getFromDict(dat.config, name[0])
196
+ return cfg[name[1]]
197
+
198
+ def set_aut2(self, dat, name, value):
199
+ cfg = getFromDict(dat.config, name[0])
200
+ cfg[name[1]] = value
201
+
202
+ def find_names_aut2(self, dat, pattern):
203
+ rex = re.compile(name)
204
+ cfg = getFromDict(dat.config, name[0])
205
+ return [(name[0], z) for z in cfg.keys() if rex.match(z)]
206
+
207
+
208
+ shortNames = {
209
+ 'CJ' : 'json_values',
210
+ 'HR' : 'heatgener_rate',
211
+ 'SR' : 'massgener_rate',
212
+ 'SE' : 'massgener_enth',
213
+ 'IN' : 'infiltration',
214
+ 'K1' : 'permeability_1',
215
+ 'K2' : 'permeability_2',
216
+ 'K3' : 'permeability_3',
217
+ 'PO' : 'porosity',
218
+ 'R1' : 'permeability_1_byrock',
219
+ 'R2' : 'permeability_2_byrock',
220
+ 'R3' : 'permeability_3_byrock',
221
+ 'RA' : 'permeability_123_byrock', #tgra963
222
+ 'RS' : 'permeability_12_byrock', #tgra963
223
+ 'RP' : 'porosity_byrock',
224
+ 'RE' : 'upflow_rech'
225
+ }
226
+
227
+
228
+ def upflow_rech(names, dat, val=None):
229
+ if val is None:
230
+ return dat.config['RechCoefficients'][names[0]]
231
+ else:
232
+ dat.config['RechCoefficients'][names[0]] = val
233
+
234
+ def heatgener_rate(names,dat,val=None):
235
+ if val is None:
236
+ for g in dat.generatorlist:
237
+ if g.name in names:
238
+ return g.gx
239
+ else:
240
+ for g in dat.generatorlist:
241
+ if g.name in names:
242
+ g.gx = val
243
+
244
+ def massgener_enth(names,dat,val=None):
245
+ if val is None:
246
+ for g in dat.generatorlist:
247
+ if g.name in names:
248
+ return g.ex
249
+ else:
250
+ for g in dat.generatorlist:
251
+ if g.name in names:
252
+ g.ex = val
253
+
254
+ def infiltration(names,dat,val=None):
255
+ if val is None:
256
+ return 999 # yet to be done
257
+ else:
258
+ # doesn't care names
259
+ from make_rain import make_rain
260
+ cfg_name = 'make_rain.cfg'
261
+ cfg_name = os.getcwd() + os.path.sep + cfg_name
262
+ cfg = config(cfg_name)
263
+ [annualrain_const, annualrain_history,
264
+ infiltration, raintemp, newwell_label, tim2sec, cols] = make_rain_proc_cfg(cfg)
265
+
266
+ infiltration = val
267
+
268
+ total_rain = make_rain(geo,dat,annualrain_const,infiltration,raintemp,newwell_label,
269
+ 60.0*60.0*24.0*365.25,cols)
270
+
271
+ def permeability_1(names,dat,val=None):
272
+ if val is None:
273
+ return dat.grid.block[names[0]].rocktype.permeability[0]
274
+ else:
275
+ from lib_rocktypes import update_rocktype_property_byblocks
276
+ update_rocktype_property_byblocks('permeability[0]',names,dat,val)
277
+
278
+ def permeability_2(names,dat,val=None):
279
+ if val is None:
280
+ return dat.grid.block[names[0]].rocktype.permeability[1]
281
+ else:
282
+ from lib_rocktypes import update_rocktype_property_byblocks
283
+ update_rocktype_property_byblocks('permeability[1]',names,dat,val)
284
+
285
+ def permeability_3(names,dat,val=None):
286
+ if val is None:
287
+ return dat.grid.block[names[0]].rocktype.permeability[2]
288
+ else:
289
+ from lib_rocktypes import update_rocktype_property_byblocks
290
+ update_rocktype_property_byblocks('permeability[2]',names,dat,val)
291
+
292
+ def porosity(names,dat,val=None):
293
+ if val is None:
294
+ return dat.grid.block[names[0]].rocktype.porosity
295
+ else:
296
+ from lib_rocktypes import update_rocktype_property_byblocks
297
+ update_rocktype_property_byblocks('porosity',names,dat,val)
298
+
299
+ def permeability_123_byrock(names,dat,val=None):
300
+ if val is None:
301
+ return dat.grid.rocktype[names[0]].permeability[0]
302
+ else:
303
+ dat.grid.rocktype[names[0]].permeability[0] = val
304
+ dat.grid.rocktype[names[0]].permeability[1] = val
305
+ dat.grid.rocktype[names[0]].permeability[2] = val
306
+
307
+ def permeability_12_byrock(names,dat,val=None):
308
+ if val is None:
309
+ return dat.grid.rocktype[names[0]].permeability[0]
310
+ else:
311
+ dat.grid.rocktype[names[0]].permeability[0] = val
312
+ dat.grid.rocktype[names[0]].permeability[1] = val
313
+