Skip to content

Commit 341b3f1

Browse files
mjrenomjreno
authored andcommitted
write runnable gwf base simulation
1 parent 4fb893c commit 341b3f1

30 files changed

+3043
-345
lines changed

docs/examples/array_example.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,12 @@
4545
constant = data_path / "constant.txt"
4646
external = data_path / "external.txt"
4747
shape = (1000, 100)
48+
type = "double"
4849

4950
# Open and load a NumPy array representation
5051

5152
fhandle = open(internal)
52-
imfa = MFArray.load(fhandle, data_path, shape, header=False)
53+
imfa = MFArray.load(fhandle, data_path, shape, type=type, header=False)
5354

5455
# Get values
5556

@@ -70,7 +71,7 @@
7071
plt.colorbar()
7172

7273
fhandle = open(constant)
73-
cmfa = MFArray.load(fhandle, data_path, shape, header=False)
74+
cmfa = MFArray.load(fhandle, data_path, shape, type=type, header=False)
7475
cvals = cmfa.value
7576
plt.imshow(cvals[0:100])
7677
plt.colorbar()
@@ -93,7 +94,7 @@
9394
# External
9495

9596
fhandle = open(external)
96-
emfa = MFArray.load(fhandle, data_path, shape, header=False)
97+
emfa = MFArray.load(fhandle, data_path, shape, type=type, header=False)
9798
evals = emfa.value
9899
evals
99100

@@ -118,7 +119,9 @@
118119

119120
fhandle = open(ilayered)
120121
shape = (3, 1000, 100)
121-
ilmfa = MFArray.load(fhandle, data_path, shape, header=False, layered=True)
122+
ilmfa = MFArray.load(
123+
fhandle, data_path, shape, type=type, header=False, layered=True
124+
)
122125
vals = ilmfa.value
123126

124127
ilmfa._value # internal storage
@@ -165,7 +168,9 @@
165168

166169
fhandle = open(clayered)
167170
shape = (3, 1000, 100)
168-
clmfa = MFArray.load(fhandle, data_path, shape, header=False, layered=True)
171+
clmfa = MFArray.load(
172+
fhandle, data_path, shape, type=type, header=False, layered=True
173+
)
169174

170175
clmfa._value
171176

@@ -218,7 +223,9 @@
218223

219224
fhandle = open(mlayered)
220225
shape = (3, 1000, 100)
221-
mlmfa = MFArray.load(fhandle, data_path, shape, header=False, layered=True)
226+
mlmfa = MFArray.load(
227+
fhandle, data_path, shape, type=type, header=False, layered=True
228+
)
222229

223230
mlmfa.how
224231

flopy4/array.py

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,16 @@ def load(cls, f, cwd, shape, header=True, **kwargs):
434434
model_shape = kwargs.pop("model_shape", None)
435435
params = kwargs.pop("blk_params", {})
436436
mempath = kwargs.pop("mempath", None)
437+
atype = kwargs.get("type", None)
438+
439+
if atype is not None:
440+
if atype == "integer":
441+
dtype = np.int32
442+
elif atype == "double":
443+
dtype = np.float64
444+
else:
445+
raise ValueError("array spec type not defined")
446+
437447
if model_shape and isinstance(shape, str):
438448
if shape == "(nodes)":
439449
n = math.prod([x for x in model_shape])
@@ -459,7 +469,7 @@ def load(cls, f, cwd, shape, header=True, **kwargs):
459469
lshp = shape[1:]
460470
objs = []
461471
for _ in range(nlay):
462-
mfa = cls._load(f, cwd, lshp, name)
472+
mfa = cls._load(f, cwd, lshp, dtype=dtype, name=name)
463473
objs.append(mfa)
464474

465475
return MFArray(
@@ -474,11 +484,17 @@ def load(cls, f, cwd, shape, header=True, **kwargs):
474484
else:
475485
kwargs.pop("layered", None)
476486
return cls._load(
477-
f, cwd, shape, layered=layered, name=name, **kwargs
487+
f,
488+
cwd,
489+
shape,
490+
layered=layered,
491+
dtype=dtype,
492+
name=name,
493+
**kwargs,
478494
)
479495

480496
@classmethod
481-
def _load(cls, f, cwd, shape, layered=False, **kwargs):
497+
def _load(cls, f, cwd, shape, layered=False, dtype=None, **kwargs):
482498
control_line = multi_line_strip(f).split()
483499

484500
if CommonNames.iprn.lower() in control_line:
@@ -491,25 +507,31 @@ def _load(cls, f, cwd, shape, layered=False, **kwargs):
491507
clpos = 1
492508

493509
if how == MFArrayType.internal:
494-
array = cls.read_array(f)
510+
array = cls.read_array(f, dtype)
495511

496512
elif how == MFArrayType.constant:
497-
array = float(control_line[clpos])
513+
if dtype == np.float64:
514+
array = float(control_line[clpos])
515+
else:
516+
array = int(control_line[clpos])
498517
clpos += 1
499518

500519
elif how == MFArrayType.external:
501520
extpath = Path(control_line[clpos])
502521
fpath = cwd / extpath
503522
with open(fpath) as foo:
504-
array = cls.read_array(foo)
523+
array = cls.read_array(foo, dtype)
505524
clpos += 1
506525

507526
else:
508527
raise NotImplementedError()
509528

510529
factor = None
511530
if len(control_line) > 2:
512-
factor = float(control_line[clpos + 1])
531+
if dtype == np.float64:
532+
factor = float(control_line[clpos + 1])
533+
else:
534+
factor = int(control_line[clpos + 1])
513535

514536
return cls(
515537
shape,
@@ -521,7 +543,7 @@ def _load(cls, f, cwd, shape, layered=False, **kwargs):
521543
)
522544

523545
@staticmethod
524-
def read_array(f):
546+
def read_array(f, dtype):
525547
"""
526548
Read a MODFLOW 6 array from an open file
527549
into a flat NumPy array representation.
@@ -538,5 +560,5 @@ def read_array(f):
538560
astr.append(line)
539561

540562
astr = StringIO(" ".join(astr))
541-
array = np.genfromtxt(astr).ravel()
563+
array = np.genfromtxt(astr, dtype=dtype).ravel()
542564
return array

flopy4/block.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ def load(cls, f, **kwargs):
225225
name = None
226226
index = None
227227
found = False
228+
period = False
228229
params = dict()
229230
members = cls.params
230231

@@ -238,12 +239,17 @@ def load(cls, f, **kwargs):
238239
if line == "\n":
239240
continue
240241
words = strip(line).lower().split()
241-
key = words[0]
242+
if period:
243+
key = "stress_period_data"
244+
else:
245+
key = words[0]
242246
if key == "begin":
243247
found = True
244248
name = words[1]
245249
if len(words) > 2 and str.isdigit(words[2]):
246250
index = int(words[2])
251+
if name == "period":
252+
period = True
247253
elif key == "end":
248254
break
249255
elif found:
@@ -268,20 +274,22 @@ def load(cls, f, **kwargs):
268274
# TODO: inject from model somehow?
269275
# and remove special handling here
270276
kwrgs["cwd"] = ""
277+
# kwrgs["type"] = param.type
271278
kwrgs["mempath"] = f"{mempath}/{name}"
272-
if ptype is not MFArray:
279+
if ptype is not MFArray and ptype is not MFList:
273280
kwrgs.pop("model_shape", None)
274281
kwrgs.pop("blk_params", None)
275282

276283
params[param.name] = ptype.load(f, **kwrgs)
284+
period = False
277285

278286
return cls(name=name, index=index, params=params)
279287

280288
def write(self, f):
281289
"""Write the block to file."""
282290
index = self.index if self.index is not None else ""
283291
begin = f"BEGIN {self.name.upper()} {index}\n"
284-
end = f"END {self.name.upper()}\n"
292+
end = f"END {self.name.upper()}\n\n"
285293

286294
f.write(begin)
287295
super().write(f)

flopy4/compound.py

Lines changed: 71 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from flopy4.array import MFArray, MFArrayType
99
from flopy4.param import MFParam, MFParams, MFReader
10-
from flopy4.scalar import MFDouble, MFInteger, MFScalar
10+
from flopy4.scalar import MFScalar
1111
from flopy4.utils import strip
1212

1313
PAD = " "
@@ -338,21 +338,39 @@ def load(cls, f, **kwargs) -> "MFList":
338338
"""Load list input with the given component parameters from a file."""
339339

340340
blk_params = kwargs.pop("blk_params", {})
341+
model_shape = kwargs.pop("model_shape", None)
341342
params = kwargs.pop("params", None)
342-
type = kwargs.pop("type", None)
343343
kwargs.pop("mname", None)
344-
kwargs.pop("shape", None)
344+
kwargs.pop("shape", None) # e.g. maxbound
345+
346+
param_lists = []
347+
param_cols = []
348+
param_types = []
349+
for k in list(params):
350+
if params[k].name == "aux" or params[k].name == "boundname":
351+
continue
352+
# raise NotImplementedError(
353+
# "boundames and auxvars not yet supported in period blocks"
354+
# )
355+
pcols = 0
356+
if params[k].shape is None or params[k].shape == "":
357+
pcols = 1
358+
elif params[k].shape == "(ncelldim)":
359+
if model_shape:
360+
pcols = len(model_shape)
361+
else:
362+
raise ValueError("model_shape not set")
363+
else:
364+
pcols = len(params[k].shape.split(","))
365+
param_cols.append(pcols)
366+
param_lists.append(list())
367+
param_types.append(params[k].type)
345368

346369
if list(params.items())[-1][1].shape == "(:)":
347-
maxsplit = len(params) - 1
370+
maxsplit = sum(param_cols) - 1
348371
else:
349372
maxsplit = -1
350373

351-
param_lists = []
352-
# TODO: support multi-dimensional params
353-
for i in range(len(params)):
354-
param_lists.append(list())
355-
356374
while True:
357375
pos = f.tell()
358376
line = f.readline()
@@ -361,9 +379,28 @@ def load(cls, f, **kwargs) -> "MFList":
361379
break
362380
else:
363381
tokens = strip(line).split(maxsplit=maxsplit)
364-
assert len(tokens) == len(param_lists)
365-
for i, token in enumerate(tokens):
366-
param_lists[i].append(token)
382+
assert len(tokens) == sum(param_cols)
383+
icol = 0
384+
for i, p in enumerate(param_lists):
385+
if param_cols[i] == 1:
386+
if param_types[i] == "integer":
387+
param_lists[i].append(int(tokens[icol]))
388+
elif param_types[i] == "double":
389+
param_lists[i].append(float(tokens[icol]))
390+
else:
391+
param_lists[i].append(tokens[icol])
392+
icol += 1
393+
else:
394+
row_l = []
395+
for j in range(param_cols[i]):
396+
if param_types[i] == "integer":
397+
row_l.append(int(tokens[icol]))
398+
elif param_types[i] == "double":
399+
row_l.append(float(tokens[icol]))
400+
else:
401+
row_l.append(tokens[icol])
402+
icol += 1
403+
param_lists[i].append(row_l)
367404

368405
if blk_params and "dimensions" in blk_params:
369406
nbound = blk_params.get("dimensions").get("nbound")
@@ -372,31 +409,41 @@ def load(cls, f, **kwargs) -> "MFList":
372409
if len(param_list) > nbound:
373410
raise ValueError("MFList nbound not satisfied")
374411

375-
list_params = MFList.create_list_params(params, param_lists, **kwargs)
376-
return cls(list_params, type=type, **kwargs)
412+
list_params = MFList.create_list_params(
413+
params, param_lists, param_cols, **kwargs
414+
)
415+
return cls(list_params, **kwargs)
377416

378417
@staticmethod
379418
def create_list_params(
380419
params: Dict[str, MFParam],
381420
param_lists: list,
421+
param_cols: list,
382422
**kwargs,
383423
) -> Dict[str, MFParam]:
384424
"""Create the param dictionary"""
385425
idx = 0
386426
list_params = dict()
387427
for param_name, param in params.items():
388-
if type(param) is MFDouble:
428+
if param_name == "aux" or param_name == "boundname":
429+
continue
430+
shape = None
431+
if param_cols[idx] == 1:
432+
shape = len(param_lists[idx])
433+
else:
434+
shape = (len(param_lists[idx]), param_cols[idx])
435+
if type(param) is MFArray and param.type == "double":
389436
list_params[param_name] = MFArray(
390-
shape=len(param_lists[idx]),
437+
shape=shape,
391438
array=np.array(param_lists[idx], dtype=np.float64),
392439
how=MFArrayType.internal,
393440
factor=1.0,
394441
path=None,
395442
**kwargs,
396443
)
397-
elif type(param) is MFInteger:
444+
elif type(param) is MFArray and param.type == "integer":
398445
list_params[param_name] = MFArray(
399-
shape=len(param_lists[idx]),
446+
shape=shape,
400447
array=np.array(param_lists[idx], dtype=np.int32),
401448
how=MFArrayType.internal,
402449
factor=1,
@@ -406,7 +453,7 @@ def create_list_params(
406453
else:
407454
list_params[param_name] = MFScalarList(
408455
value=param_lists[idx],
409-
type=type(param),
456+
# type=type(param),
410457
**kwargs,
411458
)
412459

@@ -427,5 +474,9 @@ def write(self, f, **kwargs):
427474
for i in range(count):
428475
line = f"{PAD}"
429476
for name, param in self.params.items():
430-
line += f"{param.value[i]}\t"
477+
if isinstance(param.value[i], np.ndarray):
478+
for v in param.value[i]:
479+
line += f"{v}\t"
480+
else:
481+
line += f"{param.value[i]}\t"
431482
f.write(line + "\n")

flopy4/ispec/exg_gwfgwf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ class ExgGwfgwf(MFPackage):
463463
)
464464

465465
aux = MFArray(
466-
type = "array",
466+
type = "double",
467467
block = "exchangedata",
468468
shape = "(naux)",
469469
reader = "urword",

0 commit comments

Comments
 (0)