@@ -181,6 +181,7 @@ def __init__(self, sim, modelname=None):
181181 self ._allow_splitting = True
182182
183183 self ._fdigits = 1
184+ self ._keep_external = True
184185
185186 # multi-model splitting attr
186187 self ._multimodel_exchange_gwf_names = {}
@@ -678,12 +679,13 @@ def optimize_splitting_mask(self, nparts, active_only=False, options=None, verbo
678679 else :
679680 cellids = package .packagedata .array .cellid
680681 if self ._modelgrid .grid_type == "structured" :
681- cellids = [(0 , i [1 ], i [2 ]) for i in cellids ]
682+ # skip disconnected cells in SFR package
683+ cellids = [(0 , i [1 ], i [2 ]) for i in cellids if i != (- 1 , - 1 , - 1 )]
682684 nodes = self ._modelgrid .get_node (cellids )
683685 elif self ._modelgrid .grid_type == "vertex" :
684- nodes = [i [1 ] for i in cellids ]
686+ nodes = [i [1 ] for i in cellids if i != ( - 1 , - 1 ) ]
685687 else :
686- nodes = [i [0 ] for i in cellids ]
688+ nodes = [i [0 ] for i in cellids if i != ( - 1 ,) ]
687689
688690 if isinstance (package , (modflow .ModflowGwflak , modflow .ModflowGwtlkt , modflow .ModflowGwelke )):
689691 lakenos = package .connectiondata .array .ifno + 1
@@ -758,15 +760,24 @@ def optimize_splitting_mask(self, nparts, active_only=False, options=None, verbo
758760 cellids2 = recarray .cellid2
759761 _ , nodes1 = self ._cellid_to_layer_node (cellids1 )
760762 _ , nodes2 = self ._cellid_to_layer_node (cellids2 )
761- mnums1 = membership [nodes1 ]
762- mnums2 = membership [nodes2 ]
763- ev = np .equal (mnums1 , mnums2 )
764- if np .all (ev ):
765- continue
766- idx = np .asarray (~ ev ).nonzero ()[0 ]
767- mnum_to = mnums1 [idx ]
768- adj_nodes = nodes2 [idx ]
769- membership [adj_nodes ] = mnum_to
763+ cnt = 0
764+ while cnt < len (nodes1 ):
765+ mnums1 = membership [nodes1 ]
766+ mnums2 = membership [nodes2 ]
767+ ev = np .equal (mnums1 , mnums2 )
768+ if np .all (ev ):
769+ break
770+ idx = np .asarray (~ ev ).nonzero ()[0 ]
771+ mnum_to = mnums1 [idx ]
772+ adj_nodes = np .array (nodes2 )[idx ]
773+ membership [adj_nodes ] = mnum_to
774+ cnt += 1
775+
776+ if cnt == len (nodes1 ):
777+ raise AssertionError (
778+ "Cannot uniquely spilt around HFB boundaries, try another "
779+ "value for nparts"
780+ )
770781
771782 return membership .reshape (shape )
772783
@@ -1012,6 +1023,7 @@ def _remap_nodes(self, array):
10121023 self ._offsets [m ] = {
10131024 "xorigin" : self ._modelgrid .xvertices [rmax + 1 , cmin ],
10141025 "yorigin" : self ._modelgrid .yvertices [rmax + 1 , cmin ],
1026+ "angrot" : self ._modelgrid .angrot
10151027 }
10161028 # get new nrow and ncol information
10171029 nrow = (rmax - rmin ) + 1
@@ -1035,6 +1047,7 @@ def _remap_nodes(self, array):
10351047 self ._offsets [m ] = {
10361048 "xorigin" : self ._modelgrid .xoffset ,
10371049 "yorigin" : self ._modelgrid .yoffset ,
1050+ "angrot" : self ._modelgrid .angrot
10381051 }
10391052
10401053 new_ncpl = {}
@@ -1536,6 +1549,9 @@ def _remap_array(self, item, mfarray, mapped_data, **kwargs):
15361549 # external array
15371550 tmp = fnames [lay ].split ("." )
15381551 filename = f"{ '.' .join (tmp [:- 1 ])} .{ mkey :0{self ._fdigits }d} .{ tmp [- 1 ]} "
1552+ folder_path = (self ._new_sim .sim_path / filename ).parent
1553+ if not folder_path .exists ():
1554+ folder_path .mkdir (parents = True )
15391555
15401556 cr = {
15411557 "filename" : filename ,
@@ -1621,6 +1637,9 @@ def _remap_mflist(
16211637 if how == 3 and new_recarray is not None :
16221638 tmp = fname .split ("." )
16231639 filename = f"{ '.' .join (tmp [:- 1 ])} .{ mkey :0{self ._fdigits }d} .{ tmp [- 1 ]} "
1640+ folder_path = (self ._new_sim .sim_path / filename ).parent
1641+ if not folder_path .exists ():
1642+ folder_path .mkdir (parents = True )
16241643
16251644 new_recarray = {
16261645 "data" : new_recarray ,
@@ -2040,6 +2059,10 @@ def _remap_sfr(self, package, mapped_data):
20402059 cellids [messy_idx ] = rcids
20412060
20422061 layers , nodes = self ._cellid_to_layer_node (cellids )
2062+ # adjust the messy_idx layer number
2063+ if layers is not None and messy_idx :
2064+ layers [messy_idx ] = 0
2065+
20432066 new_model , new_node = self ._get_new_model_new_node (nodes )
20442067
20452068 for mkey , model in self ._model_dict .items ():
@@ -3519,6 +3542,15 @@ def _remap_package(self, package, ismvr=False):
35193542 if "stress_period_data" in data :
35203543 if not data ["stress_period_data" ]:
35213544 continue
3545+
3546+ if self ._keep_external :
3547+ shape = self ._grid_info [mdl ][0 ]
3548+ if len (shape ) == 2 :
3549+ max_cols = shape [1 ]
3550+ else :
3551+ max_cols = shape [0 ]
3552+ self ._new_sim .simulation_data .max_columns_of_data = max_cols
3553+
35223554 paks [mdl ] = pak_cls (
35233555 self ._model_dict [mdl ], pname = package .name [0 ], ** data
35243556 )
@@ -3842,7 +3874,7 @@ def create_multi_model_exchanges(self, mname0, mname1):
38423874 filename = filename ,
38433875 )
38443876
3845- def split_model (self , array ):
3877+ def split_model (self , array , sim_ws = None ):
38463878 """
38473879 User method to split a model based on an array
38483880
@@ -3852,6 +3884,10 @@ def split_model(self, array):
38523884 integer array of new model numbers. Array must either be of
38533885 dimension (NROW, NCOL), (NCPL), or (NNODES for unstructured grid
38543886 models).
3887+ sim_ws : PathLike or str
3888+ optional directory path for writing the new simulation to. This parameter
3889+ is recommended when the model contains external files and the user would
3890+ like to preserve external linkages while splitting.
38553891
38563892 Returns
38573893 -------
@@ -3863,6 +3899,10 @@ def split_model(self, array):
38633899 "is part of a split simulation"
38643900 )
38653901
3902+ if sim_ws is None :
3903+ self ._keep_external = False
3904+ sim_ws = self ._sim .sim_path
3905+
38663906 # set number formatting string for file paths
38673907 array = np .array (array ).astype (int )
38683908 s = str (np .max (array ))
@@ -3872,7 +3912,7 @@ def split_model(self, array):
38723912
38733913 if self ._new_sim is None :
38743914 self ._new_sim = modflow .MFSimulation (
3875- version = self ._sim .version , exe_name = self ._sim .exe_name , sim_ws = self . _sim . sim_path
3915+ version = self ._sim .version , exe_name = self ._sim .exe_name , sim_ws = sim_ws
38763916 )
38773917 self ._create_sln_tdis ()
38783918
@@ -3898,6 +3938,9 @@ def split_model(self, array):
38983938 ** nam_options [mkey ],
38993939 )
39003940
3941+ if not self ._keep_external :
3942+ self ._model .set_all_data_internal (check_data = True )
3943+
39013944 for package in self ._model .packagelist :
39023945 paks = self ._remap_package (package )
39033946
@@ -3909,7 +3952,7 @@ def split_model(self, array):
39093952
39103953 return self ._new_sim
39113954
3912- def split_multi_model (self , array ):
3955+ def split_multi_model (self , array , sim_ws = None ):
39133956 """
39143957 Method to split integrated models such as GWF-GWT or GWF-GWE models.
39153958 Note: this method will not work to split multiple connected GWF models
@@ -3920,6 +3963,10 @@ def split_multi_model(self, array):
39203963 integer array of new model numbers. Array must either be of
39213964 dimension (NROW, NCOL), (NCPL), or (NNODES for unstructured grid
39223965 models).
3966+ sim_ws : PathLike or str
3967+ optional directory path for writing the new simulation to. This parameter
3968+ is recommended when the model contains external files and the user would
3969+ like to preserve external linkages while splitting.
39233970
39243971 Returns
39253972 -------
@@ -3986,7 +4033,7 @@ def split_multi_model(self, array):
39864033 new_sim = self .split_model (array )
39874034 for mname in model_names [1 :]:
39884035 self .switch_models (modelname = mname , remap_nodes = False )
3989- new_sim = self .split_model (array )
4036+ new_sim = self .split_model (array , sim_ws = sim_ws )
39904037
39914038 for mbase in model_names [1 :]:
39924039 for label in model_labels :
0 commit comments