Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions autotest/test_lgrutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,3 +215,62 @@ def test_lgrutil3():
b[1] = -2 * dz
b[2] = -3 * dz
assert np.allclose(gridprops["botm"], b)


def test_lgr_from_parent_grid():
"""Test the from_parent_grid classmethod convenience constructor."""
from flopy.discretization import StructuredGrid

# Create a parent grid with center cells marked for refinement
nlay, nrow, ncol = 1, 7, 7
delr = delc = 100.0 * np.ones(7)
top = np.zeros((nrow, ncol))
botm = -100.0 * np.ones((nlay, nrow, ncol))
idomain = np.ones((nlay, nrow, ncol), dtype=int)
idomain[:, 2:5, 2:5] = 0 # Mark center 3x3 cells for refinement

parent_grid = StructuredGrid(
delr=delr, delc=delc, top=top, botm=botm, idomain=idomain
)

# Create Lgr using the classmethod
lgr_from_classmethod = Lgr.from_parent_grid(parent_grid, idomain, ncpp=3, ncppl=1)

# Create Lgr using the traditional constructor
lgr_traditional = Lgr(
nlayp=nlay,
nrowp=nrow,
ncolp=ncol,
delrp=delr,
delcp=delc,
topp=top,
botmp=botm,
idomainp=idomain,
ncpp=3,
ncppl=1,
xllp=0.0,
yllp=0.0,
)

# Verify both methods produce the same results
assert lgr_from_classmethod.get_shape() == lgr_traditional.get_shape()
assert np.allclose(lgr_from_classmethod.delr, lgr_traditional.delr)
assert np.allclose(lgr_from_classmethod.delc, lgr_traditional.delc)
assert np.allclose(lgr_from_classmethod.top, lgr_traditional.top)
assert np.allclose(lgr_from_classmethod.botm, lgr_traditional.botm)

# Verify child grid has expected dimensions (3x3 parent cells refined to 9x9)
assert lgr_from_classmethod.get_shape() == (1, 9, 9)

# Verify gridprops can be generated
gridprops = lgr_from_classmethod.to_disv_gridprops()
assert "ncpl" in gridprops
assert "nvert" in gridprops
assert "vertices" in gridprops
assert "cell2d" in gridprops
assert "nlay" in gridprops
assert "top" in gridprops
assert "botm" in gridprops

# Expected: 40 parent cells + 81 child cells = 121 total cells
assert gridprops["ncpl"] == 121
45 changes: 45 additions & 0 deletions flopy/utils/lgrutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,51 @@ def __init__(
self.xll = xllp + float(self.delrp[0 : self.npcbeg].sum())
self.yll = yllp + float(self.delcp[self.nprend + 1 :].sum())

@classmethod
def from_parent_grid(cls, parent_grid, refine_mask, ncpp=3, ncppl=1):
"""
Create an Lgr instance from a parent StructuredGrid.

Parameters
----------
parent_grid : StructuredGrid
The parent grid
refine_mask : ndarray
Array indicating which parent cells to refine (shape: nlay, nrow, ncol).
Cells with value 0 will be refined, with value 1 remain as parent cells.
ncpp : int
Number of child cells per parent cell face (default 3)
ncppl : int or list of ints
Number of child layers per parent layer (default 1)

Returns
-------
Lgr
Local grid refinement instance

Examples
--------
>>> # Create refinement mask - refine center 3x3 cells
>>> refine_mask = np.ones((nlay, nrow, ncol))
>>> refine_mask[:, 2:5, 2:5] = 0
>>> lgr = Lgr.from_parent_grid(parent_grid, refine_mask, ncpp=3)

"""
return cls(
nlayp=parent_grid.nlay,
nrowp=parent_grid.nrow,
ncolp=parent_grid.ncol,
delrp=parent_grid.delr,
delcp=parent_grid.delc,
topp=parent_grid.top,
botmp=parent_grid.botm,
idomainp=refine_mask,
ncpp=ncpp,
ncppl=ncppl,
xllp=parent_grid.xoffset,
yllp=parent_grid.yoffset,
)

def get_shape(self):
"""
Return the shape of the child grid
Expand Down
Loading