@@ -87,6 +87,54 @@ def _path_to_record(field_name: str, path_value: Path) -> tuple:
8787 return (field_name .upper (), "FILEOUT" , str (path_value ))
8888
8989
90+ def _user_dims (value , field_value ):
91+ # terrible hack to convert flat nodes dimension to 3d structured dims.
92+ # long term solution for this is to use a custom xarray index. filters
93+ # should then have access to all dimensions needed.
94+ dims_ = set (field_value .dims ).copy ()
95+ parent = value .parent # type: ignore
96+ if parent is None :
97+ # TODO for standalone packages
98+ return field_value
99+
100+ if "nper" in dims_ :
101+ dims_ .remove ("nper" )
102+ shape = (
103+ field_value .sizes ["nper" ],
104+ parent .dims ["nlay" ],
105+ parent .dims ["nrow" ],
106+ parent .dims ["ncol" ],
107+ )
108+ dims = ("nper" , "nlay" , "nrow" , "ncol" )
109+ coords = {
110+ "nper" : field_value .coords ["nper" ],
111+ "nlay" : range (parent .dims ["nlay" ]),
112+ "nrow" : range (parent .dims ["nrow" ]),
113+ "ncol" : range (parent .dims ["ncol" ]),
114+ }
115+ else :
116+ shape = (
117+ parent .dims ["nlay" ],
118+ parent .dims ["nrow" ],
119+ parent .dims ["ncol" ],
120+ )
121+ dims = ("nlay" , "nrow" , "ncol" )
122+ coords = {
123+ "nlay" : range (parent .dims ["nlay" ]),
124+ "nrow" : range (parent .dims ["nrow" ]),
125+ "ncol" : range (parent .dims ["ncol" ]),
126+ }
127+
128+ if dims_ == {"nodes" }:
129+ field_value = xr .DataArray (
130+ field_value .data .reshape (shape ),
131+ dims = dims ,
132+ coords = coords ,
133+ )
134+
135+ return field_value
136+
137+
90138def unstructure_component (value : Component ) -> dict [str , Any ]:
91139 blockspec = dict (sorted (value .dfn .blocks .items (), key = block_sort_key )) # type: ignore
92140 blocks : dict [str , dict [str , Any ]] = {}
@@ -161,47 +209,27 @@ def unstructure_component(value: Component) -> dict[str, Any]:
161209 dim in field_value .dims for dim in ["nlay" , "nrow" , "ncol" , "nodes" ]
162210 )
163211 if has_spatial_dims :
164- # terrible hack to convert flat nodes dimension to 3d structured dims.
165- # long term solution for this is to use a custom xarray index. filters
166- # should then have access to all dimensions needed.
167- dims_ = set (field_value .dims ).copy ()
168- dims_ .remove ("nper" )
169- if dims_ == {"nodes" }:
170- parent = value .parent # type: ignore
171- field_value = xr .DataArray (
172- field_value .data .reshape (
173- (
174- field_value .sizes ["nper" ],
175- parent .dims ["nlay" ],
176- parent .dims ["nrow" ],
177- parent .dims ["ncol" ],
178- )
179- ),
180- dims = ("nper" , "nlay" , "nrow" , "ncol" ),
181- coords = {
182- "nper" : field_value .coords ["nper" ],
183- "nlay" : range (parent .dims ["nlay" ]),
184- "nrow" : range (parent .dims ["nrow" ]),
185- "ncol" : range (parent .dims ["ncol" ]),
186- },
187- name = field_value .name ,
188- )
212+ field_value = _user_dims (value , field_value )
189213
190214 period_data [field_name ] = {
191215 kper : field_value .isel (nper = kper )
192216 for kper in range (field_value .sizes ["nper" ])
193217 }
194218 else :
195- if (
196- # TODO: refactor
197- # field_name == "save_budget"
198- # or field_name == "save_head"
199- # or field_name == "print_budget"
200- # or field_name == "print_head"
201- np .issubdtype (field_value .dtype , np .str_ )
202- ):
219+ if value .__class__ .__name__ == "Oc" :
203220 period_data [field_name ] = {
204- kper : field_value [kper ] for kper in range (field_value .sizes ["nper" ])
221+ kper : field_value .values [kper ]
222+ for kper in range (field_value .sizes ["nper" ])
223+ if field_value .values [kper ] is not None
224+ }
225+ elif np .issubdtype (field_value .dtype , np .str_ ):
226+ fname = field_name
227+ if value .__class__ .__name__ == "Sto" :
228+ fname = field_name .replace ("_" , "-" )
229+ period_data [fname ] = {
230+ kper : field_value [kper ]
231+ for kper in range (field_value .sizes ["nper" ])
232+ if field_value [kper ] is not None
205233 }
206234 else :
207235 if block_name not in period_data :
@@ -212,6 +240,8 @@ def unstructure_component(value: Component) -> dict[str, Any]:
212240 if isinstance (field_value , bool ):
213241 if field_value :
214242 blocks [block_name ][field_name ] = field_value
243+ elif isinstance (field_value , xr .DataArray ):
244+ blocks [block_name ][field_name ] = _user_dims (value , field_value )
215245 else :
216246 blocks [block_name ][field_name ] = field_value
217247
@@ -223,9 +253,20 @@ def unstructure_component(value: Component) -> dict[str, Any]:
223253
224254 for arr_name , periods in period_data .items ():
225255 for kper , arr in periods .items ():
226- if kper not in period_blocks :
227- period_blocks [kper ] = {}
228- period_blocks [kper ][arr_name ] = arr
256+ if isinstance (arr , xr .DataArray ):
257+ max = arr .max ()
258+ if max == arr .min () and max == FILL_DNODATA :
259+ # don't write empty period blocks unless
260+ # to intentionally reset data
261+ pass
262+ else :
263+ if kper not in period_blocks :
264+ period_blocks [kper ] = {}
265+ period_blocks [kper ][arr_name ] = arr
266+ else :
267+ if kper not in period_blocks :
268+ period_blocks [kper ] = {}
269+ period_blocks [kper ][arr_name ] = arr .upper ()
229270
230271 for kper , block in period_blocks .items ():
231272 dataset = xr .Dataset (block )
0 commit comments