Skip to content

Commit

Permalink
Consume version_tag arg when creating model_ds
Browse files Browse the repository at this point in the history
  • Loading branch information
bdestombe committed May 28, 2024
1 parent dcdb76b commit 544ef26
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 31 deletions.
23 changes: 20 additions & 3 deletions nlmod/dims/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
logger = logging.getLogger(__name__)


def set_ds_attrs(ds, model_name, model_ws, mfversion="mf6", exe_name=None):
def set_ds_attrs(
ds, model_name, model_ws, mfversion="mf6", exe_name=None, version_tag=None
):
"""Set the attribute of a model dataset.
Parameters
Expand All @@ -31,6 +33,11 @@ def set_ds_attrs(ds, model_name, model_ws, mfversion="mf6", exe_name=None):
path to modflow executable, default is None, which assumes binaries
are available in nlmod/bin directory. Binaries can be downloaded
using `nlmod.util.download_mfbinaries()`.
version_tag : str, default None
GitHub release ID: for example "18.0" or "latest". If version_tag is provided,
the most recent installation location of MODFLOW is found in flopy metadata
that respects `version_tag`. If not found, the executables are downloaded.
Not compatible with exe_name.
Returns
-------
Expand All @@ -46,7 +53,9 @@ def set_ds_attrs(ds, model_name, model_ws, mfversion="mf6", exe_name=None):
ds.attrs["created_on"] = dt.datetime.now().strftime(fmt)

if exe_name is None:
exe_name = util.get_exe_path(exe_name=mfversion)
exe_name = util.get_exe_path(exe_name=mfversion, version_tag=version_tag)
else:
exe_name = util.get_exe_path(exe_name=exe_name, version_tag=version_tag)

ds.attrs["exe_name"] = exe_name

Expand Down Expand Up @@ -78,6 +87,7 @@ def to_model_ds(
drop_attributes=True,
transport=False,
remove_nan_layers=True,
version_tag=None,
):
"""Transform an input dataset to a groundwater model dataset.
Expand Down Expand Up @@ -136,6 +146,11 @@ def to_model_ds(
remove_nan_layers : bool, optional
if True remove layers with only nan values in the botm. Default is
True.
version_tag : str, default None
GitHub release ID: for example "18.0" or "latest". If version_tag is provided,
the most recent installation location of MODFLOW is found in flopy metadata
that respects `version_tag`. If not found, the executables are downloaded.
Not compatible with exe_name.
Returns
-------
Expand Down Expand Up @@ -176,7 +191,9 @@ def to_model_ds(
ds = extrapolate_ds(ds)

# add attributes
ds = set_ds_attrs(ds, model_name, model_ws)
ds = set_ds_attrs(
ds, model_name, model_ws, mfversion="mf6", version_tag=version_tag
)
ds.attrs["transport"] = int(transport)

# fill nan's
Expand Down
28 changes: 22 additions & 6 deletions nlmod/sim/sim.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def get_tdis_perioddata(ds, nstp="nstp", tsmult="tsmult"):
return tdis_perioddata


def sim(ds, exe_name=None):
def sim(ds, exe_name=None, version_tag=None):
"""create sim from the model dataset.
Parameters
Expand All @@ -117,9 +117,14 @@ def sim(ds, exe_name=None):
attributes: model_name, mfversion, model_ws, time_units, start,
perlen, nstp, tsmult
exe_name: str, optional
path to modflow executable, default is None, which assumes binaries
are available in nlmod/bin directory. Binaries can be downloaded
using `nlmod.util.download_mfbinaries()`.
path to modflow executable, default is None. If None, the path is
obtained from the flopy metadata that respects `version_tag`. If not
found, the executables are downloaded. Not compatible with version_tag.
version_tag : str, default None
GitHub release ID: for example "18.0" or "latest". If version_tag is provided,
the most recent installation location of MODFLOW is found in flopy metadata
that respects `version_tag`. If not found, the executables are downloaded.
Not compatible with exe_name.
Returns
-------
Expand All @@ -130,8 +135,19 @@ def sim(ds, exe_name=None):
# start creating model
logger.info("creating mf6 SIM")

if exe_name is None:
exe_name = util.get_exe_path(exe_name=ds.mfversion)
# Most likely exe_name was previously set with to_model_ds()
if exe_name is not None:
exe_name = util.get_exe_path(exe_name=exe_name, version_tag=version_tag)
elif "exe_name" in ds.attrs:
exe_name = util.get_exe_path(
exe_name=ds.attrs["exe_name"], version_tag=version_tag
)
elif "mfversion" in ds.attrs:
exe_name = util.get_exe_path(
exe_name=ds.attrs["mfversion"], version_tag=version_tag
)
else:
raise ValueError("No exe_name provided and no exe_name found in ds.attrs")

# Create the Flopy simulation object
sim = flopy.mf6.MFSimulation(
Expand Down
79 changes: 57 additions & 22 deletions nlmod/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ def get_exe_path(
"""Get the full path of the executable.
Searching for the executables is done in the following order:
0. If exe_name is a full path, return the full path of the executable.
1. The directory specified with `bindir`. Raises error if exe_name is provided
and not found. Requires enable_version_check to be False.
2. The directory used by nlmod installed in this environment.
Expand Down Expand Up @@ -143,16 +144,29 @@ def get_exe_path(
if sys.platform.startswith("win") and not exe_name.endswith(".exe"):
exe_name += ".exe"

exe_full_path = str(
get_bin_directory(
exe_name=exe_name,
bindir=bindir,
download_if_not_found=download_if_not_found,
version_tag=version_tag,
repo=repo,
# If exe_name is a full path
if Path(exe_name).exists():
enable_version_check = version_tag is not None and repo is not None

if enable_version_check:
msg = (
"Incompatible arguments. If exe_name is provided, unable to check "
"the version."
)
raise ValueError(msg)
exe_full_path = exe_name

else:
exe_full_path = str(
get_bin_directory(
exe_name=exe_name,
bindir=bindir,
download_if_not_found=download_if_not_found,
version_tag=version_tag,
repo=repo,
)
/ exe_name
)
/ exe_name
)

msg = f"Executable path: {exe_full_path}"
logger.debug(msg)
Expand All @@ -171,6 +185,7 @@ def get_bin_directory(
Get the directory where the executables are stored.
Searching for the executables is done in the following order:
0. If exe_name is a full path, return the full path of the executable.
1. The directory specified with `bindir`. Raises error if exe_name is provided
and not found. Requires enable_version_check to be False.
2. The directory used by nlmod installed in this environment.
Expand Down Expand Up @@ -218,8 +233,19 @@ def get_bin_directory(
if sys.platform.startswith("win") and not exe_name.endswith(".exe"):
exe_name += ".exe"

# If bindir is provided
enable_version_check = version_tag is not None and repo is not None

# If exe_name is a full path
if Path(exe_name).exists():
if enable_version_check:
msg = (
"Incompatible arguments. If exe_name is provided, unable to check "
"the version."
)
raise ValueError(msg)
return Path(exe_name).parent

# If bindir is provided
if bindir is not None and enable_version_check:
msg = "Incompatible arguments. If bindir is provided, unable to check the version."
raise ValueError(msg)
Expand Down Expand Up @@ -315,22 +341,31 @@ def get_flopy_bin_directories(version_tag=None, repo="executables"):
meta_list = json.loads(meta_raw)

enable_version_check = version_tag is not None and repo is not None

# To convert latest into an explicit tag
if (
SUPPRESS_EXE_VERION_CHECK = (
"NLMOD_SUPPRESS_EXE_VERION_CHECK" in os.environ
and os.environ["NLMOD_SUPPRESS_EXE_VERION_CHECK"]
).lower() in ("true", "1", "t"):
# envvars are always strings
suppress_version_check = True
logger.info(
"Suppressing version check by setting the NLMOD_SUPPRESS_EXE_VERION_CHECK "
"environment variable to True."
).lower() in ("true", "1", "t") # envvars are always strings

# To convert latest into an explicit tag
if enable_version_check and SUPPRESS_EXE_VERION_CHECK:
msg = (
"The version of the executables would have been checked, because the "
"`version_tag` is passed to `get_flopy_bin_directories()`, but is "
"suppressed by a set NLMOD_SUPPRESS_EXE_VERION_CHECK."
)
elif enable_version_check and not SUPPRESS_EXE_VERION_CHECK:
msg = (
"The version of the executables will be checked, because the "
f"`version_tag={version_tag}` is passed to `get_flopy_bin_directories()`."
)
else:
suppress_version_check = False
msg = (
"The version of the executables will not be checked, because the "
"`version_tag` is not passed to `get_flopy_bin_directories()`."
)
logger.info(msg)

if enable_version_check and not suppress_version_check:
if enable_version_check and not SUPPRESS_EXE_VERION_CHECK:
version_tag_pin = get_release(tag=version_tag, repo=repo, quiet=True)[
"tag_name"
]
Expand All @@ -353,7 +388,7 @@ def get_flopy_bin_directories(version_tag=None, repo="executables"):
return path_list


def download_mfbinaries(bindir=None, version_tag=None, repo="executables"):
def download_mfbinaries(bindir=None, version_tag="latest", repo="executables"):
"""Download and unpack platform-specific modflow binaries.
Source: USGS
Expand Down

0 comments on commit 544ef26

Please sign in to comment.