19
19
20
20
FILLNA_INT32 = np .int32 (- 2147483647 )
21
21
FILLNA_DBL = 9.96920996838687e36
22
+ lenunits = {0 : "m" , 1 : "ft" , 2 : "m" , 3 : "m" }
22
23
23
24
24
25
class ModelNetCDFDataset :
@@ -45,7 +46,6 @@ class ModelNetCDFDataset:
45
46
"""
46
47
47
48
def __init__ (self ):
48
- # TODO: grid offsets
49
49
self ._modelname = None
50
50
self ._modeltype = None
51
51
self ._dataset = None
@@ -157,6 +157,9 @@ def set_array(
157
157
):
158
158
"""
159
159
Set data in an existing array. Override this function in a derived class.
160
+ Do not use to update variables that establish the vertices and cell
161
+ structure of the grid, e.g. delr/delc or vertex/cell parameters, only
162
+ model data associated with the grid.
160
163
161
164
Args:
162
165
package (str): A package name provided as an argument to create_array().
@@ -286,64 +289,59 @@ def _set_encoding(self, **kwargs):
286
289
return encoding
287
290
288
291
def _set_projection (self ):
289
- if self ._dis :
290
- crs = None
291
- wkt = None
292
- if self ._dis .crs :
293
- try :
294
- crs = CRS .from_user_input (self ._dis .crs )
295
- wkt = crs .to_wkt ()
296
- except Exception as e :
297
- # crs = None
298
- # wkt = None
299
- warnings .warn (
300
- f"Cannot generate CRS object from user input: { e } " ,
301
- UserWarning ,
302
- )
303
-
304
- if wkt is not None :
305
- # add projection variable
306
- self ._dataset = self ._dataset .assign (
307
- {"projection" : ([], np .int32 (1 ))}
308
- )
309
- if self ._nc_type == "structured" :
310
- self ._dataset ["projection" ].attrs ["crs_wkt" ] = wkt
311
- self ._dataset ["x" ].attrs ["grid_mapping" ] = "projection"
312
- self ._dataset ["y" ].attrs ["grid_mapping" ] = "projection"
313
- elif self ._nc_type == "mesh2d" :
314
- self ._dataset ["projection" ].attrs ["wkt" ] = wkt
315
- self ._dataset ["mesh_node_x" ].attrs ["grid_mapping" ] = (
316
- "projection"
317
- )
318
- self ._dataset ["mesh_node_y" ].attrs ["grid_mapping" ] = (
319
- "projection"
320
- )
321
- self ._dataset ["mesh_face_x" ].attrs ["grid_mapping" ] = (
322
- "projection"
323
- )
324
- self ._dataset ["mesh_face_y" ].attrs ["grid_mapping" ] = (
292
+ if not self ._dis :
293
+ return
294
+
295
+ crs = None
296
+ wkt = None
297
+ projection = False
298
+ if self ._dis .crs :
299
+ try :
300
+ crs = CRS .from_user_input (self ._dis .crs )
301
+ wkt = crs .to_wkt ()
302
+ projection = True
303
+ except Exception as e :
304
+ warnings .warn (
305
+ f"Cannot generate CRS object from user input: { e } " ,
306
+ UserWarning ,
307
+ )
308
+
309
+ # update coords based on crs
310
+ coords = self ._set_coords (crs )
311
+
312
+ # Don't define projection and grid mapping if using
313
+ # geographic coordinates in the structured type
314
+ if self ._nc_type == "structured" and coords == "lon lat" :
315
+ projection = False
316
+
317
+ if projection :
318
+ # add projection variable
319
+ self ._dataset = self ._dataset .assign ({"projection" : ([], np .int32 (1 ))})
320
+ if self ._nc_type == "structured" :
321
+ self ._dataset ["projection" ].attrs ["crs_wkt" ] = wkt
322
+ self ._dataset ["x" ].attrs ["grid_mapping" ] = "projection"
323
+ self ._dataset ["y" ].attrs ["grid_mapping" ] = "projection"
324
+ elif self ._nc_type == "mesh2d" :
325
+ self ._dataset ["projection" ].attrs ["wkt" ] = wkt
326
+ self ._dataset ["mesh_node_x" ].attrs ["grid_mapping" ] = "projection"
327
+ self ._dataset ["mesh_node_y" ].attrs ["grid_mapping" ] = "projection"
328
+ self ._dataset ["mesh_face_x" ].attrs ["grid_mapping" ] = "projection"
329
+ self ._dataset ["mesh_face_y" ].attrs ["grid_mapping" ] = "projection"
330
+
331
+ # set grid_mapping and coordinates attributes
332
+ for p in self ._tags :
333
+ for l in self ._tags [p ]:
334
+ dims = self ._dataset [self ._tags [p ][l ]].dims
335
+ if (self ._nc_type == "structured" and len (dims ) > 1 ) or (
336
+ self ._nc_type == "mesh2d"
337
+ and ("nmesh_face" in dims or "nmesh_node" in dims )
338
+ ):
339
+ if projection :
340
+ self ._dataset [self ._tags [p ][l ]].attrs ["grid_mapping" ] = (
325
341
"projection"
326
342
)
327
-
328
- # update coords based on crs
329
- coords = self ._set_coords (crs )
330
-
331
- # set grid_mapping and coordinates attributes
332
- for p in self ._tags :
333
- for l in self ._tags [p ]:
334
- dims = self ._dataset [self ._tags [p ][l ]].dims
335
- if (self ._nc_type == "structured" and len (dims ) > 1 ) or (
336
- self ._nc_type == "mesh2d"
337
- and ("nmesh_face" in dims or "nmesh_node" in dims )
338
- ):
339
- if crs is not None :
340
- self ._dataset [self ._tags [p ][l ]].attrs ["grid_mapping" ] = (
341
- "projection"
342
- )
343
- if coords is not None :
344
- self ._dataset [self ._tags [p ][l ]].attrs ["coordinates" ] = (
345
- coords
346
- )
343
+ if coords is not None :
344
+ self ._dataset [self ._tags [p ][l ]].attrs ["coordinates" ] = coords
347
345
348
346
def _set_modflow_attrs (self ):
349
347
if self ._modeltype .endswith ("6" ):
@@ -545,10 +543,16 @@ def array(self, package: str, param: str, layer=None):
545
543
return self ._dataset [self ._tags [path ][- 1 ]].data
546
544
547
545
def _set_grid (self , dis ):
548
- lenunits = {0 : "m" , 1 : "feet" , 2 : "m" , 3 : "cm" }
546
+ if dis .angrot != 0.0 :
547
+ xoff = 0.0
548
+ yoff = 0.0
549
+ else :
550
+ xoff = dis .xoffset
551
+ yoff = dis .yoffset
549
552
553
+ # set coordinate var bounds
550
554
x_bnds = []
551
- xv = dis . xoffset + dis .xyedges [0 ]
555
+ xv = xoff + dis .xyedges [0 ]
552
556
for idx , val in enumerate (xv ):
553
557
if idx + 1 < len (xv ):
554
558
bnd = []
@@ -557,18 +561,17 @@ def _set_grid(self, dis):
557
561
x_bnds .append (bnd )
558
562
559
563
y_bnds = []
560
- yv = dis . yoffset + dis .xyedges [1 ]
564
+ yv = yoff + dis .xyedges [1 ]
561
565
for idx , val in enumerate (yv ):
562
566
if idx + 1 < len (yv ):
563
567
bnd = []
564
568
bnd .append (yv [idx + 1 ])
565
569
bnd .append (yv [idx ])
566
570
y_bnds .append (bnd )
567
571
568
- # x = dis.xcellcenters[0]
569
- # y = dis.ycellcenters[:, 0]
570
- x = dis .xoffset + dis .xycenters [0 ]
571
- y = dis .yoffset + dis .xycenters [1 ]
572
+ # set coordinate vars
573
+ x = xoff + dis .xycenters [0 ]
574
+ y = yoff + dis .xycenters [1 ]
572
575
z = [float (x ) for x in range (1 , dis .nlay + 1 )]
573
576
574
577
# create coordinate vars
@@ -715,8 +718,6 @@ def array(self, package: str, param: str, layer=None):
715
718
return None
716
719
717
720
def _set_grid (self , dis ):
718
- lenunits = {0 : "m" , 1 : "feet" , 2 : "m" , 3 : "cm" }
719
-
720
721
# mesh container variable
721
722
self ._dataset = self ._dataset .assign ({"mesh" : ([], np .int32 (1 ))})
722
723
self ._dataset ["mesh" ].attrs ["cf_role" ] = "mesh_topology"
@@ -770,7 +771,6 @@ def _set_grid(self, dis):
770
771
y_bnds .append (bnd )
771
772
772
773
var_d = {
773
- # TODO modflow6 and flopy results differ for mesh_face_x gwf_sto01
774
774
"mesh_face_x" : (["nmesh_face" ], dis .xcellcenters .flatten ()),
775
775
"mesh_face_xbnds" : (["nmesh_face" , "max_nmesh_face_nodes" ], x_bnds ),
776
776
"mesh_face_y" : (["nmesh_face" ], dis .ycellcenters .flatten ()),
@@ -861,9 +861,6 @@ def array(self, package: str, param: str, layer=None):
861
861
return None
862
862
863
863
def _set_grid (self , disv ):
864
- # default metric "m" when undefined
865
- lenunits = {0 : "m" , 1 : "feet" , 2 : "m" , 3 : "cm" }
866
-
867
864
# mesh container variable
868
865
self ._dataset = self ._dataset .assign ({"mesh" : ([], np .int32 (1 ))})
869
866
self ._dataset ["mesh" ].attrs ["cf_role" ] = "mesh_topology"
0 commit comments