Skip to content

Commit ec456cd

Browse files
committed
sketching
1 parent d495006 commit ec456cd

File tree

4 files changed

+99
-22
lines changed

4 files changed

+99
-22
lines changed

docs/examples/quickstart.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
from flopy4.mf6 import Simulation, Tdis
1+
from flopy4.mf6 import Sim, Tdis
22
from flopy4.mf6.gwf import Chd, Dis, Gwf, Ic, Npf, Oc
33

44
ws = "./mymodel"
55
name = "mymodel"
6-
sim = Simulation(name=name, path=ws, exe="mf6")
6+
sim = Sim(name=name, path=ws, exe="mf6")
77
tdis = Tdis(sim)
88
gwf = Gwf(sim, name=name, save_flows=True)
99
dis = Dis(gwf, nrow=10, ncol=10)

flopy4/__init__.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ def _bind_tree(self, parent):
9595
_bind_tree(parent, grandparent)
9696

9797

98-
def init_tree(self, parent=None, **kwargs):
98+
def init_tree(self, parent=None, children=None, **kwargs):
9999
"""
100100
Initialize a data tree for a component instance.
101101
"""
@@ -144,7 +144,12 @@ def init_tree(self, parent=None, **kwargs):
144144
value = kwargs.get(name, attr.default)
145145
data[name] = value
146146

147-
self.data = DataTree(data, name=cls_name)
147+
children = children or {}
148+
self.data = DataTree(
149+
data,
150+
name=cls_name,
151+
children={n: c for n, c in children.items() if c is not None},
152+
)
148153
if parent is not None:
149154
self.parent = parent
150155
_bind_tree(self, parent)

flopy4/mf6/__init__.py

Lines changed: 75 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,16 @@
88

99
from flopy4 import component, init_tree, setattribute
1010

11-
__all__ = ["Component", "Package", "Model", "Sim", "Simulation"]
11+
__all__ = [
12+
"Component",
13+
"Package",
14+
"Model",
15+
"Simulation",
16+
"Sim",
17+
"COMPONENTS",
18+
]
19+
20+
COMPONENTS = {} # component registry
1221

1322

1423
class Component(ABC):
@@ -19,6 +28,10 @@ def __init__(self, name=None, path=None):
1928
self.name = name
2029
self.path = path
2130

31+
@classmethod
32+
def __attrs_init_subclass__(cls):
33+
COMPONENTS[cls.__name__.lower()] = cls
34+
2235

2336
class Package(Component):
2437
def __init__(self, name=None, path=None):
@@ -30,14 +43,6 @@ def __init__(self, name=None, path=None):
3043
super().__init__(name, path)
3144

3245

33-
class Sim(Component):
34-
exe: Path
35-
36-
def __init__(self, name=None, path=None, exe=None):
37-
super().__init__(name, path)
38-
self.exe = exe or which("mf6")
39-
40-
4146
@component
4247
@define(init=False, slots=False, on_setattr=setattribute)
4348
class Tdis(Package):
@@ -80,9 +85,66 @@ def __init__(
8085
)
8186

8287

83-
@component
84-
@define(init=False, slots=False, on_setattr=setattribute)
85-
class Simulation(Sim):
88+
class Solution(Package):
89+
def __init__(self, name=None, path=None):
90+
super().__init__(name, path)
91+
92+
93+
@define(init=False, slots=False)
94+
class Exchange(Package):
95+
exgtype: type = field()
96+
exgfile: Path = field()
97+
exgmnamea: Optional[str] = field(default=None)
98+
exgmnameb: Optional[str] = field(default=None)
99+
100+
def __init__(
101+
self,
102+
name=None,
103+
path=None,
104+
mnamea=None,
105+
mnameb=None,
106+
):
107+
super().__init__(name, path)
108+
self.exgtype = type(self)
109+
self.exgfile = path
110+
self.exgmnamea = mnamea
111+
self.exgmnameb = mnameb
112+
113+
114+
class Simulation(Component):
115+
exe: Path
116+
86117
def __init__(self, name=None, path=None, exe=None):
118+
super().__init__(name, path)
119+
self.exe = exe or which("mf6")
120+
121+
122+
@component
123+
@define(init=False, slots=False)
124+
class Sim(Simulation):
125+
# tdis: Tdis = field(metadata={"block": "timing"})
126+
# models: dict[str, Model] = field(metadata={"block": "models"})
127+
# exchanges: dict[str, Exchange] = field(metadata={"block": "exchanges"})
128+
# solutions: dict[str, Solution] = field(metadata={"block": "solutions"})
129+
130+
def __init__(
131+
self,
132+
name=None,
133+
path=None,
134+
exe=None,
135+
tdis=None,
136+
models=None,
137+
exchanges=None,
138+
solutions=None,
139+
):
87140
super().__init__(name, path, exe)
88-
init_tree(self)
141+
# TODO pull init_tree(self) call into @component definition
142+
init_tree(
143+
self,
144+
# children={
145+
# "tdis": tdis,
146+
# "models": models,
147+
# "exchanges": exchanges,
148+
# "solutions": solutions,
149+
# },
150+
)

test/test_component.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,29 @@
11
import numpy as np
22
from xarray import DataTree
33

4-
from flopy4.mf6 import Simulation, Tdis
4+
from flopy4.mf6 import COMPONENTS, Sim, Tdis
55
from flopy4.mf6.gwf import Dis, Gwf, Ic, Npf, Oc
66

77

88
def test_components():
9-
# Create a simulation.
10-
sim = Simulation()
9+
assert COMPONENTS["sim"] is Sim
10+
assert COMPONENTS["tdis"] is Tdis
11+
assert COMPONENTS["gwf"] is Gwf
12+
assert COMPONENTS["npf"] is Npf
13+
14+
15+
def test_sim():
16+
sim = Sim()
1117
tdis = Tdis(sim=sim, nper=1, perioddata=[Tdis.PeriodData()])
1218
gwf = Gwf(sim=sim)
1319
dis = Dis(model=gwf)
1420
ic = Ic(model=gwf, strt=1.0)
1521
oc = Oc(model=gwf, perioddata=[Oc.Steps()])
1622
npf = Npf(model=gwf, icelltype=0, k=1.0)
1723

18-
# View the data tree.
19-
# sim.data
2024
assert isinstance(sim.data, DataTree)
25+
# sim.data # view the tree
26+
2127
assert "tdis" in sim.data.children
2228
assert "gwf" in sim.data.children
2329
assert "dis" in sim.data.children["gwf"].children
@@ -28,3 +34,7 @@ def test_components():
2834
assert np.array_equal(
2935
sim.data.children["gwf"].children["npf"].k, np.ones((4))
3036
)
37+
assert sim.data.children["gwf"] is gwf.data
38+
39+
# why fails?
40+
# assert gwf.parent.data.children["gwf"].children["npf"] is npf.data

0 commit comments

Comments
 (0)