Skip to content

Commit beed544

Browse files
authored
drn, rch, wel, sto (#165)
packages needed for the imod-python TWRI example
1 parent 62aa491 commit beed544

File tree

5 files changed

+317
-20
lines changed

5 files changed

+317
-20
lines changed

flopy4/mf6/gwf/chd.py

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
from typing import ClassVar, Optional
33

44
import numpy as np
5-
from attrs import define
65
from numpy.typing import NDArray
76
from xattree import dict_to_array_converter, xattree
87

@@ -15,14 +14,6 @@
1514
class Chd(Package):
1615
multi_package: ClassVar[bool] = True
1716

18-
@define(slots=False)
19-
class Steps:
20-
all: bool = field()
21-
first: bool = field()
22-
last: bool = field()
23-
steps: list[int] = field()
24-
frequency: int = field()
25-
2617
auxiliary: Optional[list[str]] = array(block="options", default=None)
2718
auxmultname: Optional[str] = field(block="options", default=None)
2819
boundnames: bool = field(block="options", default=False)
@@ -31,8 +22,8 @@ class Steps:
3122
save_flows: bool = field(block="options", default=False)
3223
ts_filerecord: Optional[Path] = field(block="options", default=None)
3324
obs_filerecord: Optional[Path] = field(block="options", default=None)
34-
dev_no_newton: bool = field(default=False, metadata={"block": "options"})
35-
maxbound: Optional[int] = field(block="dimensions", default=None)
25+
dev_no_newton: bool = field(default=False, block="options")
26+
maxbound: Optional[int] = field(block="dimensions", default=None, init=False)
3627
head: Optional[NDArray[np.float64]] = array(
3728
block="period",
3829
dims=(
@@ -63,14 +54,6 @@ class Steps:
6354
converter=dict_to_array_converter,
6455
reader="urword",
6556
)
66-
steps: Optional[NDArray[np.object_]] = array(
67-
Steps,
68-
block="period",
69-
dims=("nper", "nnodes"),
70-
default=None,
71-
converter=dict_to_array_converter,
72-
reader="urword",
73-
)
7457

7558
def __attrs_post_init__(self):
7659
# TODO set up on_setattr hooks for period block
@@ -98,5 +81,4 @@ def __attrs_post_init__(self):
9881
)
9982
maxboundname = len(np.where(boundname != ""))
10083

101-
# maxsteps = len(np.where(self.steps != None)) if self.steps is not None else 0
10284
self.maxbound = max(maxhead, maxaux, maxboundname)

flopy4/mf6/gwf/drn.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
from pathlib import Path
2+
from typing import ClassVar, Optional
3+
4+
import numpy as np
5+
from numpy.typing import NDArray
6+
from xattree import dict_to_array_converter
7+
8+
from flopy4.mf6.constants import FILL_DNODATA
9+
from flopy4.mf6.package import Package
10+
from flopy4.mf6.spec import array, field
11+
12+
13+
class Drn(Package):
14+
multi_package: ClassVar[bool] = True
15+
16+
auxiliary: Optional[list[str]] = array(block="options", default=None)
17+
auxmultname: Optional[str] = field(block="options", default=None)
18+
auxdepthname: Optional[str] = field(block="options", default=None)
19+
boundnames: bool = field(block="options", default=False)
20+
print_input: bool = field(block="options", default=False)
21+
print_flows: bool = field(block="options", default=False)
22+
save_flows: bool = field(block="options", default=False)
23+
ts_filerecord: Optional[Path] = field(block="options", default=None)
24+
obs_filerecord: Optional[Path] = field(block="options", default=None)
25+
mover: bool = field(block="options", default=False)
26+
dev_cubic_scaling: bool = field(default=False, block="options")
27+
maxbound: Optional[int] = field(block="dimensions", default=None, init=False)
28+
elev: Optional[NDArray[np.float64]] = array(
29+
block="period",
30+
dims=("nper", "nnodes"),
31+
default=None,
32+
converter=dict_to_array_converter,
33+
reader="urword",
34+
)
35+
cond: Optional[NDArray[np.float64]] = array(
36+
block="period",
37+
dims=("nper", "nnodes"),
38+
default=None,
39+
converter=dict_to_array_converter,
40+
reader="urword",
41+
)
42+
aux: Optional[NDArray[np.float64]] = array(
43+
block="period",
44+
dims=(
45+
"nper",
46+
"nnodes",
47+
),
48+
default=None,
49+
converter=dict_to_array_converter,
50+
reader="urword",
51+
)
52+
boundname: Optional[NDArray[np.str_]] = array(
53+
block="period",
54+
dims=(
55+
"nper",
56+
"nnodes",
57+
),
58+
default=None,
59+
converter=dict_to_array_converter,
60+
reader="urword",
61+
)
62+
63+
def __attrs_post_init__(self):
64+
# TODO set up on_setattr hooks for period block
65+
# arrays to update maxbound? for now do it here
66+
# in post init. but this only works when values
67+
# are set in the initializer, not when they are
68+
# set later.
69+
if self.head is None:
70+
maxhead = 0
71+
else:
72+
head = self.head if self.head.data.shape == self.head.shape else self.head.todense()
73+
maxhead = len(np.where(head != FILL_DNODATA))
74+
if self.cond is None:
75+
maxcond = 0
76+
else:
77+
cond = self.cond if self.cond.data.shape == self.cond.shape else self.cond.todense()
78+
maxcond = len(np.where(cond != FILL_DNODATA))
79+
if self.aux is None:
80+
maxaux = 0
81+
else:
82+
aux = self.aux if self.aux.data.shape == self.aux.shape else self.aux.todense()
83+
maxaux = len(np.where(aux != FILL_DNODATA))
84+
if self.boundname is None:
85+
maxboundname = 0
86+
else:
87+
boundname = (
88+
self.boundname
89+
if self.boundname.data.shape == self.boundname.shape
90+
else self.boundname.todense()
91+
)
92+
maxboundname = len(np.where(boundname != ""))
93+
94+
self.maxbound = max(maxhead, maxcond, maxaux, maxboundname)

flopy4/mf6/gwf/rch.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
from pathlib import Path
2+
from typing import ClassVar, Optional
3+
4+
import numpy as np
5+
from numpy.typing import NDArray
6+
from xattree import dict_to_array_converter, xattree
7+
8+
from flopy4.mf6.constants import FILL_DNODATA
9+
from flopy4.mf6.package import Package
10+
from flopy4.mf6.spec import array, field
11+
12+
13+
@xattree
14+
class Rch(Package):
15+
multi_package: ClassVar[bool] = True
16+
17+
fixed_cell: bool = field(block="options", default=False)
18+
auxiliary: Optional[list[str]] = array(block="options", default=None)
19+
auxmultname: Optional[str] = field(block="options", default=None)
20+
boundnames: bool = field(block="options", default=False)
21+
print_input: bool = field(block="options", default=False)
22+
print_flows: bool = field(block="options", default=False)
23+
save_flows: bool = field(block="options", default=False)
24+
ts_filerecord: Optional[Path] = field(block="options", default=None)
25+
obs_filerecord: Optional[Path] = field(block="options", default=None)
26+
maxbound: Optional[int] = field(block="dimensions", default=None, init=False)
27+
recharge: Optional[NDArray[np.float64]] = array(
28+
block="period",
29+
dims=(
30+
"nper",
31+
"nnodes",
32+
),
33+
default=None,
34+
converter=dict_to_array_converter,
35+
reader="urword",
36+
)
37+
aux: Optional[NDArray[np.float64]] = array(
38+
block="period",
39+
dims=(
40+
"nper",
41+
"nnodes",
42+
),
43+
default=None,
44+
converter=dict_to_array_converter,
45+
reader="urword",
46+
)
47+
boundname: Optional[NDArray[np.str_]] = array(
48+
block="period",
49+
dims=(
50+
"nper",
51+
"nnodes",
52+
),
53+
default=None,
54+
converter=dict_to_array_converter,
55+
reader="urword",
56+
)
57+
58+
def __attrs_post_init__(self):
59+
# TODO set up on_setattr hooks for period block
60+
# arrays to update maxbound? for now do it here
61+
# in post init. but this only works when values
62+
# are set in the initializer, not when they are
63+
# set later.
64+
if self.recharge is None:
65+
maxrecharge = 0
66+
else:
67+
recharge = self.head if self.head.data.shape == self.head.shape else self.head.todense()
68+
maxrecharge = len(np.where(recharge != FILL_DNODATA))
69+
if self.aux is None:
70+
maxaux = 0
71+
else:
72+
aux = self.aux if self.aux.data.shape == self.aux.shape else self.aux.todense()
73+
maxaux = len(np.where(aux != FILL_DNODATA))
74+
if self.boundname is None:
75+
maxboundname = 0
76+
else:
77+
boundname = (
78+
self.boundname
79+
if self.boundname.data.shape == self.boundname.shape
80+
else self.boundname.todense()
81+
)
82+
maxboundname = len(np.where(boundname != ""))
83+
84+
self.maxbound = max(maxrecharge, maxaux, maxboundname)

flopy4/mf6/gwf/sto.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
from pathlib import Path
2+
from typing import Optional
3+
4+
import numpy as np
5+
from numpy.typing import NDArray
6+
from xattree import dict_to_array_converter
7+
8+
from flopy4.mf6.package import Package
9+
from flopy4.mf6.spec import array, field
10+
11+
12+
class Sto(Package):
13+
save_flows: bool = field(block="options", default=False)
14+
storagecoefficient: bool = field(block="options", default=False)
15+
ss_confined_only: bool = field(block="options", default=False)
16+
tvs_filerecord: Optional[Path] = field(block="options", default=None)
17+
export_array_ascii: bool = field(block="options", default=False)
18+
export_array_netcdf: bool = field(block="options", default=False)
19+
dev_original_specific_storage: bool = field(block="options", default=False)
20+
dev_oldstorageformulation: bool = field(block="options", default=False)
21+
iconvert: NDArray[np.int32] = array(
22+
block="griddata",
23+
dims=("nnodes",),
24+
default=0,
25+
converter=dict_to_array_converter,
26+
)
27+
ss: NDArray[np.float64] = array(
28+
block="griddata",
29+
dims=("nnodes",),
30+
default=1e-5,
31+
converter=dict_to_array_converter,
32+
)
33+
sy: NDArray[np.float64] = array(
34+
block="griddata",
35+
dims=("nnodes",),
36+
default=0.15,
37+
converter=dict_to_array_converter,
38+
)
39+
steady_state: Optional[NDArray[np.bool_]] = array(
40+
block="period",
41+
dims=("nper",),
42+
default=None,
43+
converter=dict_to_array_converter,
44+
reader="urword",
45+
)
46+
transient: Optional[NDArray[np.bool_]] = array(
47+
block="period",
48+
dims=("nper",),
49+
default=None,
50+
converter=dict_to_array_converter,
51+
reader="urword",
52+
)

flopy4/mf6/gwf/wel.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
from pathlib import Path
2+
from typing import ClassVar, Optional
3+
4+
import numpy as np
5+
from numpy.typing import NDArray
6+
from xattree import dict_to_array_converter
7+
8+
from flopy4.mf6.constants import FILL_DNODATA
9+
from flopy4.mf6.package import Package
10+
from flopy4.mf6.spec import array, field
11+
12+
13+
class Wel(Package):
14+
multi_package: ClassVar[bool] = True
15+
16+
auxiliary: Optional[list[str]] = array(block="options", default=None)
17+
auxmultname: Optional[str] = field(block="options", default=None)
18+
boundnames: bool = field(block="options", default=False)
19+
print_input: bool = field(block="options", default=False)
20+
print_flows: bool = field(block="options", default=False)
21+
save_flows: bool = field(block="options", default=False)
22+
auto_flow_reduce: float = field(block="options", default=None)
23+
afrcsv_filerecord: Optional[Path] = field(block="options", default=None)
24+
ts_filerecord: Optional[Path] = field(block="options", default=None)
25+
obs_filerecord: Optional[Path] = field(block="options", default=None)
26+
mover: bool = field(block="options", default=False)
27+
maxbound: Optional[int] = field(block="dimensions", default=None, init=False)
28+
q: Optional[NDArray[np.float64]] = array(
29+
block="period",
30+
dims=(
31+
"nper",
32+
"nnodes",
33+
),
34+
default=None,
35+
converter=dict_to_array_converter,
36+
reader="urword",
37+
)
38+
aux: Optional[NDArray[np.float64]] = array(
39+
block="period",
40+
dims=(
41+
"nper",
42+
"nnodes",
43+
),
44+
default=None,
45+
converter=dict_to_array_converter,
46+
reader="urword",
47+
)
48+
boundname: Optional[NDArray[np.str_]] = array(
49+
block="period",
50+
dims=(
51+
"nper",
52+
"nnodes",
53+
),
54+
default=None,
55+
converter=dict_to_array_converter,
56+
reader="urword",
57+
)
58+
59+
def __attrs_post_init__(self):
60+
# TODO set up on_setattr hooks for period block
61+
# arrays to update maxbound? for now do it here
62+
# in post init. but this only works when values
63+
# are set in the initializer, not when they are
64+
# set later.
65+
if self.q is None:
66+
maxq = 0
67+
else:
68+
q = self.q if self.q.data.shape == self.q.shape else self.q.todense()
69+
maxq = len(np.where(q != FILL_DNODATA))
70+
if self.aux is None:
71+
maxaux = 0
72+
else:
73+
aux = self.aux if self.aux.data.shape == self.aux.shape else self.aux.todense()
74+
maxaux = len(np.where(aux != FILL_DNODATA))
75+
if self.boundname is None:
76+
maxboundname = 0
77+
else:
78+
boundname = (
79+
self.boundname
80+
if self.boundname.data.shape == self.boundname.shape
81+
else self.boundname.todense()
82+
)
83+
maxboundname = len(np.where(boundname != ""))
84+
85+
self.maxbound = max(maxq, maxaux, maxboundname)

0 commit comments

Comments
 (0)