Skip to content

Commit 9edba49

Browse files
wpbonellimjreno
andcommitted
jinja improvements
also update pixi section in pyproject.toml Co-authored-by: mjreno <[email protected]>
1 parent 4729eb9 commit 9edba49

File tree

3 files changed

+32
-10
lines changed

3 files changed

+32
-10
lines changed

flopy4/mf6/codec/writer/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
)
1414
_JINJA_ENV.filters["field_type"] = filters.field_type
1515
_JINJA_ENV.filters["array_how"] = filters.array_how
16-
_JINJA_ENV.filters["array_chunks"] = filters.array_chunks
16+
_JINJA_ENV.filters["array2const"] = filters.array2const
17+
_JINJA_ENV.filters["array2chunks"] = filters.array2chunks
1718
_JINJA_ENV.filters["array2string"] = filters.array2string
1819
_JINJA_ENV.filters["data2list"] = filters.data2list
1920
_JINJA_TEMPLATE_NAME = "blocks.jinja"

flopy4/mf6/codec/writer/filters.py

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
from collections.abc import Hashable, Mapping
22
from io import StringIO
3-
from typing import Any
3+
from typing import Any, Literal
44

55
import numpy as np
66
import xarray as xr
77
from modflow_devtools.dfn.schema.v2 import FieldType
88
from numpy.typing import NDArray
9+
from xattree import Scalar
910

1011
from flopy4.mf6.constants import FILL_DNODATA
1112

@@ -32,14 +33,34 @@ def field_type(value: Any) -> FieldType:
3233
raise ValueError(f"Unsupported field type: {type(value)}")
3334

3435

35-
def array_how(value: xr.DataArray) -> str:
36-
# TODO
37-
# - detect constant arrays?
38-
# - above certain size, use external?
36+
ArrayHow = Literal["constant", "internal", "external"]
37+
38+
39+
def array_how(value: xr.DataArray) -> ArrayHow:
40+
"""
41+
Determine how an array should be represented in MF6 input.
42+
Options are "constant", "internal", or "external". If the
43+
array dask-backed, assumed it's big and return "external".
44+
Otherwise there is no materialization cost to check if all
45+
values are the same, so return "constant" or "internal" as
46+
appropriate.
47+
"""
48+
if hasattr(value.data, "blocks"):
49+
return "external"
50+
if value.max() == value.min():
51+
return "constant"
3952
return "internal"
4053

4154

42-
def array_chunks(value: xr.DataArray, chunks: Mapping[Hashable, int] | None = None):
55+
def array2const(value: xr.DataArray) -> Scalar:
56+
if np.issubdtype(value.dtype, np.integer):
57+
return value.max().item()
58+
if np.issubdtype(value.dtype, np.floating):
59+
return f"{value.max().item():.8f}"
60+
return value.ravel()[0]
61+
62+
63+
def array2chunks(value: xr.DataArray, chunks: Mapping[Hashable, int] | None = None):
4364
"""
4465
Yield chunks from a dask-backed array of up to 3 dimensions.
4566
If it's not already chunked, split it into chunks of the

flopy4/mf6/codec/writer/templates/macros.jinja

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,14 @@
3232
{{ inset ~ name.upper() }}{% if "layered" in how %} LAYERED{% endif %}
3333

3434
{% if how == "constant" %}
35-
CONSTANT {{ value.item() }}
35+
CONSTANT {{ value|array2const }}
3636
{% elif how == "layered constant" %}
3737
{% for layer in value -%}
38-
CONSTANT {{ layer.item() }}
38+
CONSTANT {{ layer|array2const }}
3939
{%- endfor %}
4040
{% elif how == "internal" %}
4141
INTERNAL
42-
{% for chunk in value|array_chunks -%}
42+
{% for chunk in value|array2chunks -%}
4343
{{ (2 * inset) ~ chunk|array2string }}
4444
{%- endfor %}
4545
{% elif how == "external" %}

0 commit comments

Comments
 (0)