1919
2020FILLNA_INT32 = np .int32 (- 2147483647 )
2121FILLNA_DBL = 9.96920996838687e36
22+ lenunits = {0 : "m" , 1 : "ft" , 2 : "m" , 3 : "m" }
2223
2324
2425class ModelNetCDFDataset :
@@ -45,7 +46,6 @@ class ModelNetCDFDataset:
4546 """
4647
4748 def __init__ (self ):
48- # TODO: grid offsets
4949 self ._modelname = None
5050 self ._modeltype = None
5151 self ._dataset = None
@@ -157,6 +157,9 @@ def set_array(
157157 ):
158158 """
159159 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.
160163
161164 Args:
162165 package (str): A package name provided as an argument to create_array().
@@ -286,64 +289,59 @@ def _set_encoding(self, **kwargs):
286289 return encoding
287290
288291 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" ] = (
325341 "projection"
326342 )
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
347345
348346 def _set_modflow_attrs (self ):
349347 if self ._modeltype .endswith ("6" ):
@@ -545,10 +543,16 @@ def array(self, package: str, param: str, layer=None):
545543 return self ._dataset [self ._tags [path ][- 1 ]].data
546544
547545 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
549552
553+ # set coordinate var bounds
550554 x_bnds = []
551- xv = dis . xoffset + dis .xyedges [0 ]
555+ xv = xoff + dis .xyedges [0 ]
552556 for idx , val in enumerate (xv ):
553557 if idx + 1 < len (xv ):
554558 bnd = []
@@ -557,18 +561,17 @@ def _set_grid(self, dis):
557561 x_bnds .append (bnd )
558562
559563 y_bnds = []
560- yv = dis . yoffset + dis .xyedges [1 ]
564+ yv = yoff + dis .xyedges [1 ]
561565 for idx , val in enumerate (yv ):
562566 if idx + 1 < len (yv ):
563567 bnd = []
564568 bnd .append (yv [idx + 1 ])
565569 bnd .append (yv [idx ])
566570 y_bnds .append (bnd )
567571
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 ]
572575 z = [float (x ) for x in range (1 , dis .nlay + 1 )]
573576
574577 # create coordinate vars
@@ -715,8 +718,6 @@ def array(self, package: str, param: str, layer=None):
715718 return None
716719
717720 def _set_grid (self , dis ):
718- lenunits = {0 : "m" , 1 : "feet" , 2 : "m" , 3 : "cm" }
719-
720721 # mesh container variable
721722 self ._dataset = self ._dataset .assign ({"mesh" : ([], np .int32 (1 ))})
722723 self ._dataset ["mesh" ].attrs ["cf_role" ] = "mesh_topology"
@@ -770,7 +771,6 @@ def _set_grid(self, dis):
770771 y_bnds .append (bnd )
771772
772773 var_d = {
773- # TODO modflow6 and flopy results differ for mesh_face_x gwf_sto01
774774 "mesh_face_x" : (["nmesh_face" ], dis .xcellcenters .flatten ()),
775775 "mesh_face_xbnds" : (["nmesh_face" , "max_nmesh_face_nodes" ], x_bnds ),
776776 "mesh_face_y" : (["nmesh_face" ], dis .ycellcenters .flatten ()),
@@ -861,9 +861,6 @@ def array(self, package: str, param: str, layer=None):
861861 return None
862862
863863 def _set_grid (self , disv ):
864- # default metric "m" when undefined
865- lenunits = {0 : "m" , 1 : "feet" , 2 : "m" , 3 : "cm" }
866-
867864 # mesh container variable
868865 self ._dataset = self ._dataset .assign ({"mesh" : ([], np .int32 (1 ))})
869866 self ._dataset ["mesh" ].attrs ["cf_role" ] = "mesh_topology"
0 commit comments