Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(idm): initial netcdf integration #1617

Closed
wants to merge 27 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
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
132 changes: 131 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -566,4 +566,134 @@ jobs:
with:
name: failed-${{ matrix.os }}-${{ env.FC }}-${{ env.FC_V }}
path: modflow6/autotest/.failed


netcdf_test:
name: NetCDF testing
needs:
- lint
- build
- smoke_test
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ ubuntu-22.04, macos-12 ] #, windows-2022 ]
defaults:
run:
shell: bash -l {0}
env:
FC: gfortran
FC_V: 12
steps:

- name: Checkout modflow6
uses: actions/checkout@v4
with:
path: modflow6

- name: Setup ${{ env.FC }} ${{ env.FC_V }}
uses: fortran-lang/setup-fortran@v1
with:
compiler: gcc
version: ${{ env.FC_V }}

- name: Cache PETSc
id: cache-petsc
uses: actions/cache@v4
with:
path: petsc
key: ${{ runner.os }}-petsc

- name: Clone PETSc
if: runner.os != 'Windows' && steps.cache-petsc.outputs.cache-hit != 'true'
run: git clone -b release https://gitlab.com/petsc/petsc.git petsc

- name: Configure environment
if: runner.os == 'Linux'
run: |
echo "PKG_CONFIG_PATH=$GITHUB_WORKSPACE/petsc/linux-gnu/lib/pkgconfig" >> $GITHUB_ENV
echo "$GITHUB_WORKSPACE/petsc/linux-gnu/bin" >> $GITHUB_PATH

- name: Configure environment
if: runner.os == 'macOS'
run: |
echo "PKG_CONFIG_PATH=$GITHUB_WORKSPACE/petsc/arch-darwin-gcc-debug/lib/pkgconfig" >> $GITHUB_ENV
echo "$GITHUB_WORKSPACE/petsc/arch-darwin-gcc-debug/bin" >> $GITHUB_PATH

- name: Configure PETSc
if: runner.os == 'Linux'
working-directory: petsc
run: |
sudo ./configure PETSC_ARCH=linux-gnu --download-fblaslapack --download-openmpi
sudo make all

- name: Configure PETSc
if: runner.os == 'macOS'
working-directory: petsc
run: |
sudo ./configure PETSC_DIR="$GITHUB_WORKSPACE/petsc" PETSC_ARCH=arch-darwin-gcc-debug --download-fblaslapack --download-openmpi
sudo make all

- name: Install netcdf
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install build-essential \
libnetcdf-dev \
libnetcdff-dev \
netcdf-bin
nc-config --all
nf-config --all

- name: Install netcdf
if: runner.os == 'macOS'
run: |
bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew install netcdf-fortran
brew install gcc
nc-config --all
nf-config

- name: Setup Micromamba
uses: mamba-org/setup-micromamba@v1
with:
environment-file: modflow6/environment-nctest.yml
create-args: >-
netcdf4
init-shell: >-
bash
powershell
cache-environment: true
cache-downloads: true

- name: Build modflow6
working-directory: modflow6
run: |
meson setup builddir -Ddebug=false -Dextended=true --prefix=$(pwd) --libdir=bin
meson install -C builddir
meson test --verbose --no-rebuild -C builddir

- name: Show Meson logs
if: failure()
working-directory: modflow6
run: cat builddir/meson-logs/meson-log.txt

- name: Get executables
working-directory: modflow6/autotest
env:
GITHUB_TOKEN: ${{ github.token }}
run: pytest -v --durations 0 get_exes.py

- name: Test programs (netcdf)
working-directory: modflow6/autotest
env:
REPOS_PATH: ${{ github.workspace }}
run: |
pytest -v -n auto -m netcdf --netcdf --parallel --durations 0 --keep-failed .failed

- name: Upload failed test output
if: failure()
uses: actions/upload-artifact@v4
with:
name: failed-${{ matrix.os }}-${{ env.FC }}-${{ env.FC_V }}
path: modflow6/autotest/.failed
26 changes: 19 additions & 7 deletions autotest/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,25 @@ def pytest_addoption(parser):
default=False,
help="include parallel test cases",
)
parser.addoption(
"--netcdf",
action="store_true",
default=False,
help="include netcdf test cases",
)


def pytest_collection_modifyitems(config, items):
if config.getoption("--parallel"):
# --parallel given in cli: do not skip parallel tests
return
skip_parallel = pytest.mark.skip(reason="need --parallel option to run")
for item in items:
if "parallel" in item.keywords:
item.add_marker(skip_parallel)
if not config.getoption("--parallel"):
skip_parallel = pytest.mark.skip(
reason="need --parallel option to run"
)
for item in items:
if "parallel" in item.keywords:
item.add_marker(skip_parallel)

if not config.getoption("--netcdf"):
skip_netcdf = pytest.mark.skip(reason="need --netcdf option to run")
for item in items:
if "netcdf" in item.keywords:
item.add_marker(skip_netcdf)
18 changes: 15 additions & 3 deletions autotest/framework.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@ def run_parallel(workspace, target, ncpus) -> Tuple[bool, List[str]]:
return success, buff


def write_input(*sims, overwrite: bool = True, verbose: bool = True):
def write_input(
*sims, overwrite: bool = True, verbose: bool = True, netcdf: bool = False
):
"""
Write input files for `flopy.mf6.MFSimulation` or `flopy.mbase.BaseModel`.

Expand Down Expand Up @@ -149,7 +151,10 @@ def write_input(*sims, overwrite: bool = True, verbose: bool = True):
print(
f"Writing mf6 simulation '{sim.name}' to: {sim.sim_path}"
)
sim.write_simulation()
if netcdf:
sim.write_simulation(write_netcdf=True)
else:
sim.write_simulation()
elif isinstance(sim, flopy.mbase.BaseModel):
workspace = Path(sim.model_ws)
if any(workspace.glob("*")) and not overwrite:
Expand Down Expand Up @@ -232,6 +237,7 @@ def __init__(
check: Optional[Callable] = None,
compare: Optional[str] = "auto",
parallel=False,
netcdf=False,
ncpus=1,
htol=None,
rclose=None,
Expand All @@ -251,6 +257,7 @@ def __init__(
self.build = build
self.check = check
self.parallel = parallel
self.netcdf = netcdf
self.ncpus = [ncpus] if isinstance(ncpus, int) else ncpus
self.api_func = api_func
self.compare = compare
Expand Down Expand Up @@ -704,7 +711,12 @@ def run(self):
if len(self.ncpus) == 1 and nsims:
self.ncpus = list(repeat(self.ncpus[0], nsims))

write_input(*sims, overwrite=self.overwrite, verbose=self.verbose)
write_input(
*sims,
overwrite=self.overwrite,
verbose=self.verbose,
netcdf=self.netcdf,
)
else:
self.sims = [MFSimulation.load(sim_ws=self.workspace)]
self.buffs = [None]
Expand Down
1 change: 1 addition & 0 deletions autotest/pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ markers =
lak: tests for lake package
maw: tests for multi-aquifer well package
parallel: test relying on a parallel (MPI+PETSc) build
netcdf: test relying on a netcdf (NetCDF-FORTRAN) build
24 changes: 18 additions & 6 deletions autotest/test_gwf_auxvars.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
auxvar2 = 102.0


def build_models(idx, test):
def build_models(idx, test, netcdf=None):
nlay, nrow, ncol = 1, 10, 10
nper = 3
perlen = [1.0, 1.0, 1.0]
Expand Down Expand Up @@ -70,14 +70,22 @@ def build_models(idx, test):
delc=delc,
top=90.0,
botm=0.0,
filename=f"{name}.nc" if netcdf else f"{name}.dis",
)

# initial conditions
ic = flopy.mf6.ModflowGwfic(gwf, strt=strt)
ic = flopy.mf6.ModflowGwfic(
gwf, strt=strt, filename=f"{name}.nc" if netcdf else f"{name}.ic"
)

# node property flow
npf = flopy.mf6.ModflowGwfnpf(
gwf, save_flows=True, icelltype=1, k=1.0, k33=0.01
gwf,
save_flows=True,
icelltype=1,
k=1.0,
k33=0.01,
filename=f"{name}.nc" if netcdf else f"{name}.npf",
)
# storage
sto = flopy.mf6.ModflowGwfsto(
Expand All @@ -100,7 +108,7 @@ def build_models(idx, test):
gwf,
stress_period_data=chdspdict,
save_flows=False,
filename=f"{name}.chd",
filename=f"{name}.nc" if netcdf else f"{name}.chd",
)

# MAW
Expand Down Expand Up @@ -298,12 +306,16 @@ def check_output(idx, test):


@pytest.mark.parametrize("idx, name", enumerate(cases))
def test_mf6model(idx, name, function_tmpdir, targets):
@pytest.mark.parametrize(
"netcdf", [0, pytest.param(1, marks=pytest.mark.netcdf)]
)
def test_mf6model(idx, name, function_tmpdir, targets, netcdf):
test = TestFramework(
name=name,
workspace=function_tmpdir,
build=lambda t: build_models(idx, t),
build=lambda t: build_models(idx, t, netcdf),
check=lambda t: check_output(idx, t),
targets=targets,
netcdf=netcdf,
)
test.run()
30 changes: 24 additions & 6 deletions autotest/test_gwf_bnd_negative_cond.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
]


def build_models(idx, test):
def build_models(idx, test, netcdf=None):
# static model data
# temporal discretization
nper = 1
Expand Down Expand Up @@ -87,21 +87,32 @@ def build_models(idx, test):
delc=delc,
top=top,
botm=botm,
filename=f"{name}.nc" if netcdf else f"{name}.dis",
)

# initial conditions
ic = flopy.mf6.ModflowGwfic(gwf, strt=strt)
ic = flopy.mf6.ModflowGwfic(
gwf, strt=strt, filename=f"{name}.nc" if netcdf else f"{name}.ic"
)

# node property flow
npf = flopy.mf6.ModflowGwfnpf(gwf, icelltype=0, k=hk)
npf = flopy.mf6.ModflowGwfnpf(
gwf,
icelltype=0,
k=hk,
filename=f"{name}.nc" if netcdf else f"{name}.npf",
)

# chd files
# chd data
spd = [
[(0, 0, 0), 1.0],
]
chd = flopy.mf6.modflow.ModflowGwfchd(
gwf, stress_period_data=spd, pname="chd-1"
gwf,
stress_period_data=spd,
pname="chd-1",
filename=f"{name}.nc" if netcdf else f"{name}.chd",
)

bnd_loc = (0, 0, 1)
Expand All @@ -117,20 +128,23 @@ def build_models(idx, test):
auxiliary=["mult"],
auxmultname="mult",
stress_period_data=[(bnd_loc, top, cond, mult)],
filename=f"{name}.nc" if netcdf else f"{name}.drn",
)
elif name.startswith("riv"):
riv = flopy.mf6.ModflowGwfriv(
gwf,
auxiliary=["mult"],
auxmultname="mult",
stress_period_data=[(bnd_loc, 1.0, cond, top, mult)],
filename=f"{name}.nc" if netcdf else f"{name}.riv",
)
elif name.startswith("ghb"):
ghb = flopy.mf6.ModflowGwfghb(
gwf,
auxiliary=["mult"],
auxmultname="mult",
stress_period_data=[(bnd_loc, top, cond, mult)],
filename=f"{name}.nc" if netcdf else f"{name}.ghb",
)

return sim
Expand Down Expand Up @@ -169,13 +183,17 @@ def check_output(idx, test):


@pytest.mark.parametrize("idx, name", enumerate(cases))
def test_mf6model(idx, name, function_tmpdir, targets):
@pytest.mark.parametrize(
"netcdf", [0, pytest.param(1, marks=pytest.mark.netcdf)]
)
def test_mf6model(idx, name, function_tmpdir, targets, netcdf):
test = TestFramework(
name=name,
workspace=function_tmpdir,
targets=targets,
build=lambda t: build_models(idx, t),
build=lambda t: build_models(idx, t, netcdf),
check=lambda t: check_output(idx, t),
netcdf=netcdf,
xfail=True,
)
test.run()
Loading
Loading