@@ -23,12 +23,21 @@ def __init__(self, *args, **kwargs):
2323 "ncol" : "j" ,
2424 "nodes" : "node" ,
2525 }
26+
27+ # Compute world coordinates (x, y, z)
28+ world_coords = self ._compute_world_coordinates ()
29+
30+ # Index coordinates
2631 self ._coords = {
2732 "k" : xr .DataArray (np .arange (self .nlay , dtype = int ), dims = ("nlay" ,)),
2833 "i" : xr .DataArray (np .arange (self .nrow , dtype = int ), dims = ("nrow" ,)),
2934 "j" : xr .DataArray (np .arange (self .ncol , dtype = int ), dims = ("ncol" ,)),
3035 "node" : xr .DataArray (np .arange (self .nnodes , dtype = int ), dims = ("nodes" ,)),
3136 }
37+
38+ # Add world coordinates
39+ self ._coords .update (world_coords )
40+
3241 data_vars = {
3342 "delr" : self .delr ,
3443 "delc" : self .delc ,
@@ -43,8 +52,56 @@ def __init__(self, *args, **kwargs):
4352 .set_xindex ("i" , PandasIndex )
4453 .set_xindex ("j" , PandasIndex )
4554 .set_xindex ("node" , PandasIndex )
55+ .set_xindex ("x" , PandasIndex )
56+ .set_xindex ("y" , PandasIndex )
57+ .set_xindex ("z" , PandasIndex )
4658 )
4759
60+ def _compute_world_coordinates (self ) -> dict :
61+ """
62+ Compute x, y, z world coordinates from grid geometry.
63+
64+ Returns
65+ -------
66+ dict
67+ Dictionary with 'x', 'y', 'z' coordinate DataArrays
68+ """
69+ # Get grid extent
70+ xmin , xmax , ymin , ymax = self .extent
71+
72+ # Compute x coordinates (cell centers)
73+ delr = np .atleast_1d (self .delr [0 ] if hasattr (self .delr , '__getitem__' ) and not isinstance (self .delr , np .ndarray ) else self .delr )
74+ if delr .size == 1 :
75+ delr = np .full (self .ncol , delr [0 ])
76+ x = xmin + np .cumsum (delr ) - 0.5 * delr
77+
78+ # Compute y coordinates (cell centers)
79+ delc = np .atleast_1d (self .delc [0 ] if hasattr (self .delc , '__getitem__' ) and not isinstance (self .delc , np .ndarray ) else self .delc )
80+ if delc .size == 1 :
81+ delc = np .full (self .nrow , delc [0 ])
82+ y = ymax - np .cumsum (delc ) + 0.5 * delc
83+
84+ # Compute z coordinates (layer centers)
85+ # Use top and botm to compute layer centers
86+ top_2d = np .atleast_2d (self .top )
87+ botm_3d = np .atleast_3d (self .botm ).reshape (self .nlay , self .nrow , self .ncol )
88+
89+ # Layer center z coordinates: average of top and bottom per layer
90+ z = np .zeros (self .nlay )
91+ for k in range (self .nlay ):
92+ if k == 0 :
93+ layer_top = top_2d .mean ()
94+ else :
95+ layer_top = botm_3d [k - 1 ].mean ()
96+ layer_bot = botm_3d [k ].mean ()
97+ z [k ] = (layer_top + layer_bot ) / 2.0
98+
99+ return {
100+ "x" : xr .DataArray (x , dims = ("ncol" ,)),
101+ "y" : xr .DataArray (y , dims = ("nrow" ,)),
102+ "z" : xr .DataArray (z , dims = ("nlay" ,)),
103+ }
104+
48105 @property
49106 def dataset (self ) -> xr .Dataset :
50107 return self ._dataset
@@ -55,21 +112,21 @@ def delc(self):
55112 return None
56113 dims = ("ncol" ,)
57114 coord_name = self ._dims_coords [dims [0 ]]
58- coords = coords = {coord_name : self ._coords [coord_name ]}
115+ coords = {coord_name : self ._coords [coord_name ], "x" : self . _coords [ "x" ]}
59116 return xr .DataArray (super ().delc , coords = coords , dims = dims ).set_xindex (
60117 coord_name , PandasIndex
61- )
118+ ). set_xindex ( "x" , PandasIndex )
62119
63120 @property
64121 def delr (self ):
65122 if self .__delr is None :
66123 return None
67124 dims = ("nrow" ,)
68125 coord_name = self ._dims_coords [dims [0 ]]
69- coords = {coord_name : self ._coords [coord_name ]}
126+ coords = {coord_name : self ._coords [coord_name ], "y" : self . _coords [ "y" ] }
70127 return xr .DataArray (super ().delr , coords = coords , dims = dims ).set_xindex (
71128 coord_name , PandasIndex
72- )
129+ ). set_xindex ( "y" , PandasIndex )
73130
74131 @property
75132 def delz (self ):
@@ -80,22 +137,29 @@ def delz(self):
80137 self ._dims_coords [dims [2 ]],
81138 )
82139 coords = {coord_name : self ._coords [coord_name ] for coord_name in coord_names }
140+ coords .update ({"x" : self ._coords ["x" ], "y" : self ._coords ["y" ], "z" : self ._coords ["z" ]})
83141 return (
84142 xr .DataArray (super ().delz , coords = coords , dims = dims )
85143 .set_xindex (coord_names [0 ], PandasIndex )
86144 .set_xindex (coord_names [1 ], PandasIndex )
87145 .set_xindex (coord_names [2 ], PandasIndex )
146+ .set_xindex ("x" , PandasIndex )
147+ .set_xindex ("y" , PandasIndex )
148+ .set_xindex ("z" , PandasIndex )
88149 )
89150
90151 @property
91152 def top (self ):
92153 dims = ("nrow" , "ncol" )
93154 coord_names = (self ._dims_coords [dims [0 ]], self ._dims_coords [dims [1 ]])
94155 coords = {coord_name : self ._coords [coord_name ] for coord_name in coord_names }
156+ coords .update ({"x" : self ._coords ["x" ], "y" : self ._coords ["y" ]})
95157 return (
96158 xr .DataArray (super ().top , coords = coords , dims = dims )
97159 .set_xindex (coord_names [0 ], PandasIndex )
98160 .set_xindex (coord_names [1 ], PandasIndex )
161+ .set_xindex ("x" , PandasIndex )
162+ .set_xindex ("y" , PandasIndex )
99163 )
100164
101165 @property
@@ -107,11 +171,15 @@ def botm(self):
107171 self ._dims_coords [dims [2 ]],
108172 )
109173 coords = {coord_name : self ._coords [coord_name ] for coord_name in coord_names }
174+ coords .update ({"x" : self ._coords ["x" ], "y" : self ._coords ["y" ], "z" : self ._coords ["z" ]})
110175 return (
111176 xr .DataArray (super ().botm , coords = coords , dims = dims )
112177 .set_xindex (coord_names [0 ], PandasIndex )
113178 .set_xindex (coord_names [1 ], PandasIndex )
114179 .set_xindex (coord_names [2 ], PandasIndex )
180+ .set_xindex ("x" , PandasIndex )
181+ .set_xindex ("y" , PandasIndex )
182+ .set_xindex ("z" , PandasIndex )
115183 )
116184
117185 @property
@@ -123,11 +191,15 @@ def idomain(self):
123191 self ._dims_coords [dims [2 ]],
124192 )
125193 coords = {coord_name : self ._coords [coord_name ] for coord_name in coord_names }
194+ coords .update ({"x" : self ._coords ["x" ], "y" : self ._coords ["y" ], "z" : self ._coords ["z" ]})
126195 return (
127196 xr .DataArray (super ().idomain , coords = coords , dims = dims )
128197 .set_xindex (coord_names [0 ], PandasIndex )
129198 .set_xindex (coord_names [1 ], PandasIndex )
130199 .set_xindex (coord_names [2 ], PandasIndex )
200+ .set_xindex ("x" , PandasIndex )
201+ .set_xindex ("y" , PandasIndex )
202+ .set_xindex ("z" , PandasIndex )
131203 )
132204
133205
0 commit comments