diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c181447651d..873f5469f50 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -149,18 +149,32 @@ jobs: - name: Get executables working-directory: modflow6/autotest + env: + GITHUB_TOKEN: ${{ github.token }} run: pytest -v --durations 0 get_exes.py - - name: Test programs + - name: Test working-directory: modflow6/autotest run: | if [ "${{ github.ref_name }}" == "master" ]; then - pytest -v -n auto --durations 0 -m "not developmode" + pytest -v -n auto --durations 0 -m "not repo and not developmode" else - pytest -v -n auto --durations 0 + pytest -v -n auto --durations 0 -m "not repo" fi - - name: Test scripts + - name: Test mf5to6 models + working-directory: modflow6/autotest + run: pytest -v -n auto --durations 0 test_testmodels_mf5to6.py + env: + REPOS_PATH: ${{ github.workspace }} + + - name: Test mf6 models + working-directory: modflow6/autotest + run: pytest -v -n auto --durations 0 test_testmodels_mf6.py + env: + REPOS_PATH: ${{ github.workspace }} + + - name: Test dist scripts working-directory: modflow6/distribution env: GITHUB_TOKEN: ${{ github.token }} @@ -221,17 +235,31 @@ jobs: - name: Get executables working-directory: modflow6/autotest + env: + GITHUB_TOKEN: ${{ github.token }} run: pytest -v --durations 0 get_exes.py - - name: Test modflow6 + - name: Test working-directory: modflow6/autotest run: | if [ "${{ github.ref_name }}" == "master" ]; then - pytest -v -n auto --durations 0 -m "not developmode" + pytest -v -n auto --durations 0 -m "not repo and not developmode" else - pytest -v -n auto --durations 0 + pytest -v -n auto --durations 0 -m "not repo" fi + - name: Test mf5to6 models + working-directory: modflow6/autotest + run: pytest -v -n auto --durations 0 test_testmodels_mf5to6.py + env: + REPOS_PATH: ${{ github.workspace }} + + - name: Test mf6 models + working-directory: modflow6/autotest + run: pytest -v -n auto --durations 0 test_testmodels_mf6.py + env: + REPOS_PATH: ${{ github.workspace }} + test_ifort: name: Test (ifort) needs: @@ -258,12 +286,6 @@ jobs: repository: MODFLOW-USGS/modflow6-testmodels path: modflow6-testmodels - - name: Checkout modflow6-examples - uses: actions/checkout@v3 - with: - repository: MODFLOW-USGS/modflow6-examples - path: modflow6-examples - - name: Setup Micromamba uses: mamba-org/provision-with-micromamba@main with: @@ -282,23 +304,6 @@ jobs: $mamba_bin = "C:\Users\runneradmin\micromamba-root\envs\modflow6\Scripts" echo $mamba_bin | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - - name: Cache modflow6 examples - id: cache-examples - uses: actions/cache@v3 - with: - path: modflow6-examples/examples - key: modflow6-examples-${{ hashFiles('modflow6-examples/scripts/**') }} - - - name: Install extra Python packages - if: steps.cache-examples.outputs.cache-hit != 'true' - working-directory: modflow6-examples/etc - run: pip install -r requirements.pip.txt - - - name: Build example models - if: steps.cache-examples.outputs.cache-hit != 'true' - working-directory: modflow6-examples/etc - run: python ci_build_files.py - - name: Update version files working-directory: modflow6/distribution run: python update_version.py @@ -327,46 +332,84 @@ jobs: - name: Get executables if: runner.os != 'Windows' working-directory: modflow6/autotest + env: + GITHUB_TOKEN: ${{ github.token }} run: pytest -v --durations 0 get_exes.py - name: Get executables (Windows) if: runner.os == 'Windows' working-directory: modflow6/autotest shell: pwsh + env: + GITHUB_TOKEN: ${{ github.token }} run: pytest -v --durations 0 get_exes.py - - name: Test programs + - name: Test if: runner.os != 'Windows' working-directory: modflow6/autotest + env: + GITHUB_TOKEN: ${{ github.token }} run: | if [ "${{ github.ref_name }}" == "master" ]; then - pytest -v -n auto --durations 0 -m "not developmode" + pytest -v -n auto --durations 0 -m "not repo and not developmode" else - pytest -v -n auto --durations 0 + pytest -v -n auto --durations 0 -m "not repo" fi - - name: Test programs (Windows) + - name: Test (Windows) if: runner.os == 'Windows' working-directory: modflow6/autotest shell: pwsh + env: + GITHUB_TOKEN: ${{ github.token }} run: | if ( "${{ github.ref_name }}" -eq "master" ) { - pytest -v -n auto --durations 0 -m "not developmode" + pytest -v -n auto --durations 0 -m "not repo and not developmode" } else { - pytest -v -n auto --durations 0 + pytest -v -n auto --durations 0 -m "not repo" } - - name: Test scripts + - name: Test mf5to6 models + if: runner.os != 'Windows' + working-directory: modflow6/autotest + run: pytest -v -n auto --durations 0 test_testmodels_mf5to6.py + env: + REPOS_PATH: ${{ github.workspace }} + + - name: Test mf5to6 models (Windows) + if: runner.os == 'Windows' + working-directory: modflow6/autotest + shell: pwsh + run: pytest -v -n auto --durations 0 test_testmodels_mf5to6.py + env: + REPOS_PATH: ${{ github.workspace }} + + - name: Test mf6 models + if: runner.os != 'Windows' + working-directory: modflow6/autotest + run: pytest -v -n auto --durations 0 test_testmodels_mf6.py + env: + REPOS_PATH: ${{ github.workspace }} + + - name: Test mf6 models (Windows) + if: runner.os == 'Windows' + working-directory: modflow6/autotest + shell: pwsh + run: pytest -v -n auto --durations 0 test_testmodels_mf6.py + env: + REPOS_PATH: ${{ github.workspace }} + + - name: Test dist scripts if: runner.os != 'Windows' working-directory: modflow6/distribution + run: pytest -v --durations 0 env: GITHUB_TOKEN: ${{ github.token }} - run: pytest -v --durations 0 - - name: Test scripts (Windows) + - name: Test dist scripts (Windows) if: runner.os == 'Windows' working-directory: modflow6/distribution shell: pwsh + run: pytest -v --durations 0 env: GITHUB_TOKEN: ${{ github.token }} - run: pytest -v --durations 0 diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index ff97a6ad8f6..1fdd8ae8c16 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -71,8 +71,7 @@ jobs: - name: Test building files from dfn's for LaTeX working-directory: modflow6/autotest - run: | - pytest -v build_mfio_tex.py + run: pytest -v build_mfio_tex.py - name: Setup GNU Fortran ${{ env.GCC_V }} uses: awvwgk/setup-fortran@main @@ -103,17 +102,17 @@ jobs: - name: Run benchmarks working-directory: modflow6/distribution + env: + GITHUB_TOKEN: ${{ github.token }} run: python benchmark.py - name: Run sphinx working-directory: modflow6/.build_rtd_docs - run: | - make html + run: make html - name: Show results working-directory: modflow6/distribution - run: | - cat run-time-comparison.md + run: cat run-time-comparison.md - name: Upload comparison uses: actions/upload-artifact@v3 diff --git a/.github/workflows/large.yml b/.github/workflows/examples.yml similarity index 89% rename from .github/workflows/large.yml rename to .github/workflows/examples.yml index 3abe23604ff..3ab94dc5332 100644 --- a/.github/workflows/large.yml +++ b/.github/workflows/examples.yml @@ -1,4 +1,4 @@ -name: MODFLOW 6 large models +name: MODFLOW 6 example models on: schedule: - cron: '0 6 * * *' # run at 6 AM UTC every day @@ -20,7 +20,7 @@ jobs: fail-fast: false matrix: fc: [ ifort, gfortran ] - repo: [ examples, largetestmodels ] + repo: [ examples, testmodels, largetestmodels ] defaults: run: shell: bash -l {0} @@ -93,15 +93,16 @@ jobs: - name: Get executables working-directory: modflow6/autotest - run: | - pytest -v --durations 0 get_exes.py + env: + GITHUB_TOKEN: ${{ github.token }} + run: pytest -v --durations 0 get_exes.py - name: Update flopy working-directory: modflow6/autotest - run: | - python update_flopy.py + run: python update_flopy.py - name: Run tests working-directory: modflow6/autotest - run: | - pytest -v -n auto --durations 0 test_z03_${{ matrix.repo }}.py \ No newline at end of file + run: pytest -v -n auto --durations 0 test_${{ matrix.repo }}.py + env: + REPOS_PATH: ${{ github.workspace }} diff --git a/DEVELOPER.md b/DEVELOPER.md index ddafa361611..ed828b89b10 100644 --- a/DEVELOPER.md +++ b/DEVELOPER.md @@ -1,42 +1,83 @@ -# Building and Testing MODFLOW 6 + + +**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + +- [Developing MODFLOW 6](#developing-modflow-6) + - [Prerequisites](#prerequisites) + - [Git](#git) + - [Fortran compiler](#fortran-compiler) + - [GNU Fortran](#gnu-fortran) + - [Linux](#linux) + - [macOS](#macos) + - [Windows](#windows) + - [Intel Fortran](#intel-fortran) + - [Windows](#windows-1) + - [Python](#python) + - [Dependencies](#dependencies) + - [`meson`](#meson) + - [`fprettify`](#fprettify) + - [`pymake`](#pymake) + - [`flopy`](#flopy) + - [Optional tools](#optional-tools) + - [GNU Make](#gnu-make) + - [Visual Studio](#visual-studio) + - [Doxygen & LaTeX](#doxygen--latex) + - [Installation](#installation) + - [Building](#building) + - [Testing](#testing) + - [Configuring a test environment](#configuring-a-test-environment) + - [Building the local version](#building-the-local-version) + - [Rebuilding the last release and installing related programs](#rebuilding-the-last-release-and-installing-related-programs) + - [Updating `flopy` plugins](#updating-flopy-plugins) + - [External model repositories](#external-model-repositories) + - [Test models](#test-models) + - [Example models](#example-models) + - [Running tests](#running-tests) + - [Running tests in parallel](#running-tests-in-parallel) + - [Selecting tests with markers](#selecting-tests-with-markers) + + + +# Developing MODFLOW 6 + +This document describes how to set up a development environment to modify, build and test MODFLOW 6. Details on how to contribute your code to the repository are found in the separate document [CONTRIBUTING.md](CONTRIBUTING.md). + + +## Prerequisites -This document describes how to set up your development environment to build and test MODFLOW 6. -It also explains the basic mechanics of using `git`. Details on how to contribute your code to the repository are found in the separate document [CONTRIBUTING.md](CONTRIBUTING.md) - -* [Prerequisite Software](#prerequisite-software) -* [Getting the Sources](#getting-the-sources) -* [Building](#building) -* [Running Tests Locally](#running-tests-locally) - -See the [contribution guidelines](https://github.com/MODFLOW-USGS/modflow6/blob/develop/CONTRIBUTING.md) -if you'd like to contribute to MODFLOW 6. +Before you can build and test MODFLOW 6, you must install and configure the +following on your development machine: -## Prerequisite Software +- git +- Python3.8+ +- a modern Fortran compiler -Before you can build and test MODFLOW 6, you must install and configure the -following products on your development machine. +Some additional, optional tools are also discussed below. ### Git [Git](https://git-scm.com) and/or the **GitHub app** (for [Mac](https://mac.github.com) or [Windows](https://windows.github.com)). [GitHub's Guide to Installing Git](https://help.github.com/articles/set-up-git) is a good source of information. +### Fortran compiler + +The GNU Fortran compiler `gfortran` or the Intel Fortran compiler `ifort` can be used to compile MODFLOW 6. -### gfortran (version 4.9 to 10) +#### GNU Fortran -gfortran can be used to compile MODFLOW 6 and associated utilities and generate distributable files. +GNU Fortran can be installed on all three major platforms. -#### Linux +##### Linux - fedora-based: `dnf install gcc-gfortran` - debian-based: `apt install gfortran` -#### macOS +##### macOS - [Homebrew](https://brew.sh/): `brew install gcc` - [MacPorts](https://www.macports.org/): `sudo port install gcc10` -#### Windows +##### Windows - Download the Minimalist GNU for Windows (MinGW) installer from Source Forge: https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/installer/mingw-w64-install.exe @@ -48,45 +89,91 @@ gfortran can be used to compile MODFLOW 6 and associated utilities and generate `Path` variable in the User Variables (the top table). Click the `New` button and enter the location of the `mingw64/bin` directory. +#### Intel Fortran + +Intel Fortran can also be used to compile MODFLOW 6 and associated utilities. The `ifort` compiler is available in the [Intel oneAPI HPC Toolkit](https://software.intel.com/content/www/us/en/develop/tools/oneapi/hpc-toolkit/download.html). An installer is bundled with the download. A minimal + +A number of environment variables must be set before using Intel Fortran. General information can be found [here](https://www.intel.com/content/www/us/en/develop/documentation/oneapi-programming-guide/top/oneapi-development-environment-setup.html), with specific instructions to configure a shell session for `ifort` [here](https://www.intel.com/content/www/us/en/develop/documentation/fortran-compiler-oneapi-dev-guide-and-reference/top/compiler-setup/use-the-command-line/specifying-the-location-of-compiler-components.html). + +##### Windows + +On Windows, [Visual Studio](https://visualstudio.microsoft.com) and a number of libraries must be installed for `ifort` to work. The required libraries can be installed by ticking the "Desktop Development with C++" checkbox in the Visual Studio Installer's Workloads tab. + +**Note:** Invoking the `setvars.bat` scripts from a Powershell session will *not* put `ifort` on the path, since [batch script environments are local to their process](https://stackoverflow.com/a/49028002/6514033). Either invoke `ifort` from command prompt or relaunch PowerShell, e.g. + +``` +cmd.exe "/K" '"C:\Program Files (x86)\Intel\oneAPI\setvars-vcvarsall.bat" && "C:\Program Files (x86)\Intel\oneAPI\compiler\latest\env\vars.bat" && powershell' +``` + ### Python -Install Python, for example via [miniconda](https://docs.conda.io/en/latest/miniconda.html) or [Anaconda](https://www.anaconda.com/products/individual). -Then create a new environment by executing the following at the root of this repository +Python 3.8+ is required to run MODFLOW 6 tests. A Conda distribution (e.g. [miniconda](https://docs.conda.io/en/latest/miniconda.html) or [Anaconda](https://www.anaconda.com/products/individual) is recommended. Python dependencies are specified in `environment.yml`. To create an environment, run from the project root: + +``` +conda env create -f environment.yml ``` -conda env create --force -f environment.yml + +To update an existing environment: + +```shell +conda env update -f environment.yml ``` -### ifort (optional) +#### Dependencies -Intel fortran can be used to compile MODFLOW 6 and associated utilities and generate distributable files (if not using gfortran). -Download the Intel oneAPI HPC Toolkit: https://software.intel.com/content/www/us/en/develop/tools/oneapi/hpc-toolkit/download.html +This project depends critically on a few Python packages for building, linting and testing tasks: -Documentation describing how to set the intel environment variables can be found [here](https://www.intel.com/content/www/us/en/develop/documentation/oneapi-programming-guide/top/oneapi-development-environment-setup.html). +- `meson` +- `fprettify` +- `pymake` +- `flopy` -#### Windows +These are each described briefly below. The Conda `environment.yml` contains a number of other dependencies also required for various development tasks, but they are not described in detail here. -- Visual Studio with the appropriate redistributable libraries must be installed for ifort to compile on Windows. -- Install Visual Studio, which can be found [here](https://visualstudio.microsoft.com/). Note: the latest version of Visual Studio, 2022, requires a sufficiently new version of the Intel OneAPI as well. -- The redistributable libraries can installed via ticking the "Desktop Development with C++" checkbox in the Visual Studio Installer in the Workloads tab. +##### `meson` -### Doxygen & LaTeX (optional) +[Meson](https://mesonbuild.com/index.html) is recommended for building MODFLOW 6 and is included in `environment.yml`. It can also be [installed independently](https://mesonbuild.com/Getting-meson.html) — note that if you do so you will need to manually add the executable to the [PATH](https://en.wikipedia.org/wiki/PATH_(variable)). -[Doxygen](https://www.doxygen.nl/index.html) is used to generate the [MODFLOW 6 source code documentation](https://modflow-usgs.github.io/modflow6/). [Graphviz](https://graphviz.org/) is used by doxygen to produce source code diagrams. [LaTeX](https://www.latex-project.org/) is used to generate the MODFLOW 6 release notes and Input/Output documents (docs/mf6io/mf6io.nightlybuild). -These programs can be installed from various sources, including by conda, macports, or from individual sources such as https://www.tug.org/. Details about USGS LaTeX libraries can be seen in addition to linux installs in the CI workflow for the docs (`.github/workflows/ci-docs.yml`). +##### `fprettify` -### fprettify +[`fprettify`](https://github.com/pseewald/fprettify) can be used to format Fortran source code and in combination with the [MODFLOW 6 fprettify configuration](https://github.com/MODFLOW-USGS/modflow6/blob/develop/distribution/.fprettify.yaml) establishes a contribution standard for properly formatted MODFLOW 6 Fortran source. This tool can be installed with `pip` or `conda` and used from the command line or integrated with a [VSCode](https://github.com/MODFLOW-USGS/modflow6/blob/develop/.vscode/README.md) or Visual Studio development environment. The `fprettify` package is included in the Conda environment in `environment.yml`. See [contribution guidelines](https://github.com/MODFLOW-USGS/modflow6/blob/develop/CONTRIBUTING.md) for additional information. -[fprettify](https://github.com/pseewald/fprettify) can be used to format Fortran source code and in combination with the [MODFLOW 6 fprettify configuration](https://github.com/MODFLOW-USGS/modflow6/blob/develop/distribution/.fprettify.yaml) establishes a contribution standard for properly formatted MODFLOW 6 Fortran source. This tool can be installed with `pip` or `conda` and used from the command line or integrated with a [VSCode](https://github.com/MODFLOW-USGS/modflow6/blob/develop/.vscode/README.md) or Visual Studio development environment. See [contribution guidelines](https://github.com/MODFLOW-USGS/modflow6/blob/develop/CONTRIBUTING.md) for additional information. +##### `pymake` -## Getting the Sources +The `mfpymake` package can build MODFLOW 6 and related artifacts (e.g. makefiles) and is used by several build- or release-related scripts. The `mfpymake` package is included in the Conda environment in `environment.yml`. To install separately, follow the instructions as explained on the README of the [repository](https://github.com/modflowpy/pymake). The README also demonstrates basic usage. + +##### `flopy` + +[`flopy`](https://github.com/modflowpy/flopy) is used extensively throughout the MODFLOW 6 tests, to create, run and post-process models. + +Like MODFLOW 6, `flopy` is modular — for each MODFLOW 6 package there is a corresponding `flopy` plugin. Plugins are generated dynamically from DFN files stored in this repository under `doc/mf6io/mf6ivar/dfn`. + +### Optional tools + +Some other tools are useful but not required to develop MODFLOW 6. + +#### GNU Make + +This repository provides makefiles, generated by `mfpymake`, which can be used to build MODFLOW 6 with [GNU Make](https://www.gnu.org/software/make/). For further instructions we refer to the [GNU Make Manual](https://www.gnu.org/software/make/manual/). + +#### Visual Studio + +Visual Studio installers can be downloaded from the [official website](https://visualstudio.microsoft.com/). MODFLOW 6 solution files can be found in the `msvs` folder. + +#### Doxygen & LaTeX + +[Doxygen](https://www.doxygen.nl/index.html) is used to generate the [MODFLOW 6 source code documentation](https://modflow-usgs.github.io/modflow6/). [Graphviz](https://graphviz.org/) is used by doxygen to produce source code diagrams. [LaTeX](https://www.latex-project.org/) is used to generate the MODFLOW 6 release notes and Input/Output documents (docs/mf6io/mf6io.nightlybuild). + +These programs can be installed from various sources, including by conda, macports, or from individual sources such as https://www.tug.org/. Details about USGS LaTeX libraries can be seen in addition to linux installs in the CI workflow for the docs (`.github/workflows/ci-docs.yml`). + +## Installation Fork and clone the MODFLOW 6 repository: -1. Login to your GitHub account or create one by following the instructions given - [here](https://github.com/signup/free). +1. Login to your GitHub account or create one by following the instructions given [here](https://github.com/signup/free). 2. [Fork](http://help.github.com/forking) the [main MODFLOW 6](https://github.com/MODFLOW-USGS/modflow6). -3. Clone your fork of the MODFLOW 6 repository and define an `upstream` remote pointing back to the MODFLOW 6 repository that you forked in the first place. +3. Clone your fork of the MODFLOW 6 repository and create an `upstream` remote pointing back to your fork. ```shell # Clone your GitHub repository: @@ -101,15 +188,15 @@ git remote add upstream https://github.com/MODFLOW-USGS/modflow6.git ## Building -### Meson +Meson is the recommended build tool for MODFLOW 6. [Meson](https://mesonbuild.com/Getting-meson.html) must be installed and on your [PATH](https://en.wikipedia.org/wiki/PATH_(variable)). Creating and activating the Conda environment `environment.yml` should be sufficient for this. -First, install [Meson](https://mesonbuild.com/Getting-meson.html) and assure it is in your [PATH](https://en.wikipedia.org/wiki/PATH_(variable)). -When using Visual Studio Code, you can use tasks as described [here](.vscode/README.md). -For the more general instructions, continue to read this section. +Meson build configuration files are provided for MODFLOW 6 as well as `zbud6` and `mf5to6` utility programs: -First configure the build directory. -Per default it uses the compiler flags for a release build. -If you want to create a debug build, add `-Doptimization=0` to the following `setup` command. +- `meson.build` +- `utils/zonebudget/meson.build` +- `utils/mf5to6/meson.build` + +To build MODFLOW 6, first configure the build directory. By default Meson uses compiler flags for a release build. To create a debug build, add `-Doptimization=0` to the following `setup` command. ```shell # bash (linux and macOS) @@ -131,79 +218,155 @@ In order to run the tests the binaries have to be installed: meson install -C builddir ``` -The binaries can then be found in the `bin` folder. -`meson install` also triggers a compilation if necessary. -Therefore, executing `meson install` is enough to get up-to-date binaries in the `bin` folder. +The binaries can then be found in the `bin` folder. `meson install` also triggers a compilation if necessary, so executing `meson install` is enough to get up-to-date binaries in the `bin` folder. + +**Note:** If using Visual Studio Code, you can use tasks as described [here](.vscode/README.md) to automate the above. -### Visual Studio +## Testing -As of October 2021, debugging with Visual Studio tends to be more convenient than with other solutions. -First, download Visual Studio from the [official website](https://visualstudio.microsoft.com/). -The solution files can be found in the `msvs` folder. +MODFLOW 6 tests are driven with [`pytest`](https://docs.pytest.org/en/7.1.x/), with the help of plugins like `pytest-xdist` and `pytest-cases`. Testing dependencies are included in the Conda environment `environment.yml`. -### Pymake +### Configuring a test environment -Follow the installation instructions as explained on the README of the [repository](https://github.com/modflowpy/pymake). -The README also explains how to build MODFLOW 6 with it. +A few tasks must be completed before running tests: -### Make +- build local MODFLOW 6 development version +- rebuild the last MODFLOW 6 release +- install additional executables +- update FloPy plugins +- clone MODFLOW 6 test model and example repositories -We also provide make files which can be used to build MODFLOW 6 with [GNU Make](https://www.gnu.org/software/make/). -For the build instructions we refer to the [GNU Make Manual](https://www.gnu.org/software/make/manual/). +Tests expect binaries to live in the `bin` directory relative to the project root, as configured above in the `meson` commands. Binaries are organized as follows: +- local development binaries in the top-level `bin` folder +- executables rebuilt in development mode from the latest release in `bin/rebuilt` +- related programs installed from the [executables distribution](https://github.com/MODFLOW-USGS/executables/releases) live in `bin/downloaded` -## Running Tests Locally +#### Building the local version -For complete testing as done on the CI, clone your fork of the modflow6-testmodels repository (via either ssh or https, ssh shown here): +Before running tests, the local development version of MODFLOW 6 must be built with `meson` as described above. The `autotest/build_exes.py` script is provided as a shortcut to easily rebuild local binaries. The script can be run from the project root with: ```shell -git clone git@github.com:/modflow6-testmodels.git +python autotest/build_exes.py ``` -* The modflow6-testmodels repository must be cloned in the same directory that contains the modflow6 repository. -To run tests first change directory to the `autotest` folder: +Alternatively, it can be run from the `autotest` directory with `pytest`: ```shell -cd modflow6/autotest +pytest build_exes.py ``` -Update your flopy installation by executing +By default, binaries will be placed in the `bin` directory relative to the project root, as in the `meson` commands described above. To change the location of the binaries, use the `--path` option. + +#### Rebuilding the last release and installing related programs + +Tests require the latest official MODFLOW 6 release to be compiled in develop mode with the same Fortran compiler as the development version. A number of binaries distributed from the [executables repo](https://github.com/MODFLOW-USGS/executables) must also be installed. The script `autotest/get_exes.py` does both of these things. It can be run from the project root with: ```shell -python update_flopy.py +python autotest/get_exes.py ``` -The tests require other MODFLOW-related binary executables, distributed from https://github.com/MODFLOW-USGS/executables. -Testing also requires a binary executable of the last MODFLOW 6 officially released version, compiled in develop mode with the currently configured compiler. To download MODFLOW-related binaries and to rebuild the last official MODFLOW 6 release, execute: +Alternatively, from the `autotest` directory: ```shell -pytest -v get_exes.py +pytest get_exes.py ``` -Unless you built and installed MODFLOW 6 binaries with meson, you will also have to execute the following command to build the binaries: +By default, binaries will be placed in the `bin` directory relative to the project root, as in the `meson` commands described above. Nested `bin/downloaded` and `bin/rebuilt` directories are created to contain the rebuilt last release and the downloaded executables, respectively. To change the location of the binaries, use the `--path` option. + +#### Updating `flopy` plugins + +Plugins should be regenerated from DFN files before running tests for the first time or after definition files change. This can be done with the `autotest/update_flopy.py` script, which wipes and regenerates plugin classes for the `flopy` installed in the Python environment. + +**Note:** if you've installed a local version of `flopy` from source, running this script can overwrite files in your repository. + +The script accepts a single optional argument, the path to the folder containing definition files. By default DFN files are assumed to live in `doc/mf6io/mf6ivar/dfn`, making the following identical: + +```shell +python autotest/update_flopy.py +python autotest/update_flopy.py doc/mf6io/mf6ivar/dfn +``` + +#### External model repositories + +While a significant fraction of test cases create their own models programmatically, the full suite tests MODFLOW 6 against example models provided in three repositories: + +- [`MODFLOW-USGS/modflow6-testmodels`](https://github.com/MODFLOW-USGS/modflow6-testmodels) +- [`MODFLOW-USGS/modflow6-largetestmodels`](https://github.com/MODFLOW-USGS/modflow6-largetestmodels) +- [`MODFLOW-USGS/modflow6-examples`](https://github.com/MODFLOW-USGS/modflow6-examples) + +By default, the tests expect these repositories level with (i.e. in the same parent directory as) the `modflow6` repository on the filesystem. If the repositories are located somewhere on your machine, the `REPOS_PATH` environment variable can be set to point to the parent directory containing the repository folders. + +##### Test models + +The test model repos can simply be cloned (ideally, into the parent directory of the `modflow6` repository, so that repositories live side-by-side): + +```shell +git clone MODFLOW-USGS/modflow6-testmodels +git clone MODFLOW-USGS/modflow6-largetestmodels +``` + +##### Example models + +First clone the example models repo: + +```shell +git clone MODFLOW-USGS/modflow6-examples +``` + +The example models require some setup after cloning. First configure a Python environment, ```shell -pytest -v build_exes.py +pip install -r etc/requirements.pip.txt ``` -Then the tests can be run with commands similar to these: +Then from the `etc` folder, run: ```shell -# Build MODFLOW 6 tests -pytest -v +python ci_build_files.py +``` + +This will build the examples for subsequent use by the tests. + +### Running tests + +Tests are driven by `pytest`. The `pytest` command should be invoked from the `autotest` directory. -# Build MODFLOW 6 example tests -pytest -v test_z01_testmodels_mf6.py +To run tests in a particular file, showing verbose output, use: -# Build MODFLOW 5 to 6 converter example tests -pytest -v test_z02_testmodels_mf5to6.py +```shell +pytest -v ``` -The tests can be run in parallel by adding the flag "-n" which accepts an argument for the specific number of processes to use or "auto" to let pytest decide: +#### Running tests in parallel + +To run all tests in parallel, run: ```shell pytest -v -n auto ``` -You should execute the test suites before submitting a PR to Github. -All the tests are executed on our Continuous Integration infrastructure and a pull request can only be merged once all tests pass. +The number of processors to use can be specified explicitly by substituting an integer for `auto`. See the [`pytest-xdist`](https://pytest-xdist.readthedocs.io/en/latest/) docs for more information on `-n auto` and other options for running tests in parallel. + +#### Selecting tests with markers + +Markers can be used to select subsets of tests. Markers provided in `pytest.ini` include: + +- `slow`: tests that take longer than a few seconds to complete +- `regression`: tests comparing results from multiple versions + +Markers can be used with the `-m ` option, and can be applied in boolean combinations with `and`, `or` and `not`. For instance, to run fast tests in parallel, excluding regression tests: + +```shell +pytest -v -n auto -m "not slow and not regression" +``` + +The `--smoke` (short `-S`) flag, provided by `modflow-devtools` is an alias for the above: + +```shell +pytest -v -n auto -S +``` + +Smoke testing is intended to cover a reasonable fraction of the codebase while completing quickly enough to run often during development. See [`modflow-devtools`](https://github.com/MODFLOW-USGS/modflow-devtools) for more information. Several other fixtures and utilities from `modflow-devtools` are used throughout the tests. + +**Note:** the entire test suite should pass before a pull request is submitted. Tests run in GitHub Actions CI and a PR can only be merged with passing tests. See [`CONTRIBUTING.md`](CONTRIBUTING.md) for more information. diff --git a/README.md b/README.md index f4e8f192285..b34d25890b3 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ This is the development repository for the USGS MODFLOW 6 Hydrologic Model. The [![GitHub release](https://img.shields.io/github/release/MODFLOW-USGS/modflow6.svg)](https://github.com/MODFLOW-USGS/modflow6/releases/latest) [![MODFLOW 6 continuous integration](https://github.com/MODFLOW-USGS/modflow6/actions/workflows/ci.yml/badge.svg)](https://github.com/MODFLOW-USGS/modflow6/actions/workflows/ci.yml) [![MODFLOW 6 documentation](https://github.com/MODFLOW-USGS/modflow6/actions/workflows/docs.yml/badge.svg)](https://github.com/MODFLOW-USGS/modflow6/actions/workflows/docs.yml) -[![MODFLOW 6 large models](https://github.com/MODFLOW-USGS/modflow6/actions/workflows/large.yml/badge.svg)](https://github.com/MODFLOW-USGS/modflow6/actions/workflows/large.yml) +[![MODFLOW 6 example models](https://github.com/MODFLOW-USGS/modflow6/actions/workflows/examples.yml/badge.svg)](https://github.com/MODFLOW-USGS/modflow6/actions/workflows/examples.yml) [![MODFLOW 6 intel nightly build](https://github.com/MODFLOW-USGS/modflow6-nightly-build/actions/workflows/nightly-build-intel.yml/badge.svg)](https://github.com/MODFLOW-USGS/modflow6-nightly-build/actions/workflows/nightly-build-intel.yml) ## Branches @@ -44,6 +44,7 @@ This repository contains an `./autotest` folder with python scripts for building * [modflowpy/pymake](https://github.com/modflowpy/pymake) * [modflowpy/flopy](https://github.com/modflowpy/flopy) +* [MODFLOW-USGS/modflow6-examples](https://github.com/MODFLOW-USGS/modflow6-examples) * [MODFLOW-USGS/modflow6-testmodels](https://github.com/MODFLOW-USGS/modflow6-testmodels) * [MODFLOW-USGS/modflow6-largetestmodels](https://github.com/MODFLOW-USGS/modflow6-largetestmodels) * [MODFLOW-USGS/executables](https://github.com/MODFLOW-USGS/executables) diff --git a/autotest/binary_file_writer.py b/autotest/binary_file_writer.py deleted file mode 100644 index 5d8771a0424..00000000000 --- a/autotest/binary_file_writer.py +++ /dev/null @@ -1,202 +0,0 @@ -import numpy as np - - -def write_head( - fbin, - data, - kstp=1, - kper=1, - pertim=1.0, - totim=1.0, - text=" HEAD", - ilay=1, -): - dt = np.dtype( - [ - ("kstp", np.int32), - ("kper", np.int32), - ("pertim", np.float64), - ("totim", np.float64), - ("text", "S16"), - ("ncol", np.int32), - ("nrow", np.int32), - ("ilay", np.int32), - ] - ) - nrow = data.shape[0] - ncol = data.shape[1] - h = np.array((kstp, kper, pertim, totim, text, ncol, nrow, ilay), dtype=dt) - h.tofile(fbin) - data.tofile(fbin) - return - - -def write_budget( - fbin, - data, - kstp=1, - kper=1, - text=" FLOW-JA-FACE", - imeth=1, - delt=1.0, - pertim=1.0, - totim=1.0, - text1id1=" GWF-1", - text2id1=" GWF-1", - text1id2=" GWF-1", - text2id2=" NPF", -): - dt = np.dtype( - [ - ("kstp", np.int32), - ("kper", np.int32), - ("text", "S16"), - ("ndim1", np.int32), - ("ndim2", np.int32), - ("ndim3", np.int32), - ("imeth", np.int32), - ("delt", np.float64), - ("pertim", np.float64), - ("totim", np.float64), - ] - ) - - if imeth == 1: - ndim1 = data.shape[0] - ndim2 = 1 - ndim3 = -1 - h = np.array( - ( - kstp, - kper, - text, - ndim1, - ndim2, - ndim3, - imeth, - delt, - pertim, - totim, - ), - dtype=dt, - ) - h.tofile(fbin) - data.tofile(fbin) - - elif imeth == 6: - ndim1 = 1 - ndim2 = 1 - ndim3 = -1 - h = np.array( - ( - kstp, - kper, - text, - ndim1, - ndim2, - ndim3, - imeth, - delt, - pertim, - totim, - ), - dtype=dt, - ) - h.tofile(fbin) - - # write text1id1, ... - dt = np.dtype( - [ - ("text1id1", "S16"), - ("text1id2", "S16"), - ("text2id1", "S16"), - ("text2id2", "S16"), - ] - ) - h = np.array((text1id1, text1id2, text2id1, text2id2), dtype=dt) - h.tofile(fbin) - - # write ndat (number of floating point columns) - colnames = data.dtype.names - ndat = len(colnames) - 2 - dt = np.dtype([("ndat", np.int32)]) - h = np.array([(ndat,)], dtype=dt) - h.tofile(fbin) - - # write auxiliary column names - naux = ndat - 1 - if naux > 0: - auxtxt = [f"{colname:16}" for colname in colnames[3:]] - auxtxt = tuple(auxtxt) - dt = np.dtype([(colname, "S16") for colname in colnames[3:]]) - h = np.array(auxtxt, dtype=dt) - h.tofile(fbin) - - # write nlist - nlist = data.shape[0] - dt = np.dtype([("nlist", np.int32)]) - h = np.array([(nlist,)], dtype=dt) - h.tofile(fbin) - - # write the data - data.tofile(fbin) - - pass - else: - raise Exception(f"unknown method code {imeth}") - return - - -def uniform_flow_field(qx, qy, qz, shape, delr=None, delc=None, delv=None): - - nlay, nrow, ncol = shape - - # create spdis array for the uniform flow field - dt = np.dtype( - [ - ("ID1", np.int32), - ("ID2", np.int32), - ("FLOW", np.float64), - ("QX", np.float64), - ("QY", np.float64), - ("QZ", np.float64), - ] - ) - spdis = np.array( - [(id1, id1, 0.0, qx, qy, qz) for id1 in range(nlay * nrow * ncol)], - dtype=dt, - ) - - # create the flowja array for the uniform flow field (assume top-bot = 1) - flowja = [] - if delr is None: - delr = 1.0 - if delc is None: - delc = 1.0 - if delv is None: - delv = 1.0 - for k in range(nlay): - for i in range(nrow): - for j in range(ncol): - # diagonal - flowja.append(0.0) - # up - if k > 0: - flowja.append(-qz * delr * delc) - # back - if i > 0: - flowja.append(-qy * delr * delv) - # left - if j > 0: - flowja.append(qx * delc * delv) - # right - if j < ncol - 1: - flowja.append(-qx * delc * delv) - # front - if i < nrow - 1: - flowja.append(qy * delr * delv) - # bottom - if k < nlay - 1: - flowja.append(qz * delr * delc) - flowja = np.array(flowja, dtype=np.float64) - return spdis, flowja diff --git a/autotest/budget_file_compare.py b/autotest/budget_file_compare.py deleted file mode 100644 index cd69f2ccdac..00000000000 --- a/autotest/budget_file_compare.py +++ /dev/null @@ -1,120 +0,0 @@ -# utility for comparing two MODFLOW 6 budget files - -# To use this eval_bud_diff function on a gwf or gwt budget file, -# the function may need ia, in order to exclude comparison of the residual -# term, which is stored in the diagonal position of the flowja array. -# The following code can be used to extract ia from the grb file. -# get ia/ja from binary grid file -# fname = '{}.dis.grb'.format(os.path.basename(sim.name)) -# fpth = os.path.join(sim.simpath, fname) -# grbobj = flopy.mf6.utils.MfGrdFile(fpth) -# ia = grbobj._datadict['IA'] - 1 - - -import os - -import numpy as np - - -def eval_bud_diff(fpth, b0, b1, ia=None, dtol=1e-6): - diffmax = 0.0 - difftag = "None" - difftime = None - fail = False - - # build list of cbc data to retrieve - avail = b0.get_unique_record_names() - - # initialize list for storing totals for each budget term terms - cbc_keys = [] - for t in avail: - if isinstance(t, bytes): - t = t.decode() - t = t.strip() - cbc_keys.append(t) - - # open a summary file and write header - f = open(fpth, "w") - line = f"{'Time':15s}" - line += f" {'Datatype':15s}" - line += f" {'File 1':15s}" - line += f" {'File 2':15s}" - line += f" {'Difference':15s}" - f.write(line + "\n") - f.write(len(line) * "-" + "\n") - - # get data from cbc file - kk = b0.get_kstpkper() - times = b0.get_times() - for idx, (k, t) in enumerate(zip(kk, times)): - v0sum = 0.0 - v1sum = 0.0 - for key in cbc_keys: - v0 = b0.get_data(kstpkper=k, text=key)[0] - v1 = b1.get_data(kstpkper=k, text=key)[0] - if isinstance(v0, np.recarray): - v0 = v0["q"].sum() - v1 = v1["q"].sum() - else: - v0 = v0.flatten() - v1 = v1.flatten() - if key == "FLOW-JA-FACE": - # Set residual (stored in diagonal of flowja) to zero - if ia is None: - raise Exception("ia is required for model flowja") - idiagidx = ia[:-1] - v0[idiagidx] = 0.0 - v1[idiagidx] = 0.0 - v0 = v0.sum() - v1 = v1.sum() - - # sum all of the values - if key != "AUXILIARY": - v0sum += v0 - v1sum += v1 - - diff = v0 - v1 - if abs(diff) > abs(diffmax): - diffmax = diff - difftag = key - difftime = t - if abs(diff) > dtol: - fail = True - line = f"{t:15g}" - line += f" {key:15s}" - line += f" {v0:15g}" - line += f" {v1:15g}" - line += f" {diff:15g}" - f.write(line + "\n") - - # evaluate the sums - diff = v0sum - v1sum - if abs(diff) > dtol: - fail = True - line = f"{t:15g}" - line += f" {'TOTAL':15s}" - line += f" {v0sum:15g}" - line += f" {v1sum:15g}" - line += f" {diff:15g}" - f.write(line + "\n") - - msg = f"\nSummary of changes in {os.path.basename(fpth)}\n" - msg += "-" * 72 + "\n" - msg += f"Maximum cbc difference: {diffmax}\n" - msg += f"Maximum cbc difference time: {difftime}\n" - msg += f"Maximum cbc datatype: {difftag}\n" - if fail: - msg += f"Maximum cbc criteria exceeded: {dtol}" - assert not fail, msg - - # close summary file and print the final message - f.close() - print(msg) - - msg = f"sum of first cbc file flows ({v0sum}) " + f"exceeds dtol ({dtol})" - assert abs(v0sum) < dtol, msg - - msg = f"sum of second cbc file flows ({v1sum}) " + f"exceeds dtol ({dtol})" - assert abs(v1sum) < dtol, msg - - return diff --git a/autotest/build_exes.py b/autotest/build_exes.py index fd9b22a51e7..3211d1219d8 100644 --- a/autotest/build_exes.py +++ b/autotest/build_exes.py @@ -1,156 +1,33 @@ -# Build targets +import argparse +from pathlib import Path -# to use ifort on windows, run this -# python build_exes.py -fc ifort +import pytest +from modflow_devtools.build import meson_build -# can compile only mf6 directly using this command: -# python -c "import build_exes; build_exes.test_build_modflow6()" +from conftest import get_project_root_path -import os -import pathlib as pl -import subprocess as sp -import sys -from contextlib import contextmanager -from framework import running_on_CI +_repository = "MODFLOW-USGS/modflow6" +_project_root_path = get_project_root_path() +_bin_path = _project_root_path / "bin" -if running_on_CI(): - print("running on CI environment") - os.environ["PYMAKE_DOUBLE"] = "1" -# set OS dependent extensions -eext = "" -soext = ".so" -if sys.platform.lower() == "win32": - eext = ".exe" - soext = ".dll" -elif sys.platform.lower() == "darwin": - soext = ".dylib" +@pytest.fixture +def bin_path(): + return _bin_path -mfexe_pth = "temp/mfexes" -# use the line below to set fortran compiler using environmental variables -# os.environ["FC"] = "ifort" - -# some flags to check for errors in the code -# add -Werror for compilation to terminate if errors are found -strict_flags = ( - "-fall-intrinsics " - "-Wtabs -Wline-truncation -Wunused-label " - "-Wunused-variable -pedantic -std=f2008 " - "-Wcharacter-truncation" -) - - -@contextmanager -def set_directory(path: str): - """Sets the cwd within the context - - Args: - path (Path): The path to the cwd - - Yields: - None - """ - - origin = os.path.abspath(os.getcwd()) - path = os.path.abspath(path) - try: - os.chdir(path) - print(f"change from {origin} -> {path}") - yield - finally: - os.chdir(origin) - print(f"change from {path} -> {origin}") - - -def relpath_fallback(pth): - try: - # throws ValueError on Windows if pth is on a different drive - return os.path.relpath(pth) - except ValueError: - return os.path.abspath(pth) - - -def create_dir(pth): - # create pth directory - print(f"creating... {os.path.abspath(pth)}") - os.makedirs(pth, exist_ok=True) - - msg = f"could not create... {os.path.abspath(pth)}" - assert os.path.exists(pth), msg - - -def set_compiler_environment_variable(): - fc = None - - # parse command line arguments - for idx, arg in enumerate(sys.argv): - if arg.lower() == "-fc": - fc = sys.argv[idx + 1] - elif arg.lower().startswith("-fc="): - fc = arg.split("=")[1] - - # determine if fc needs to be set to the FC environmental variable - env_var = os.getenv("FC", default="gfortran") - if fc is None and fc != env_var: - fc = env_var - - # validate Fortran compiler - fc_options = ( - "gfortran", - "ifort", +def test_meson_build(bin_path): + meson_build( + project_path=_project_root_path, + build_path=_project_root_path / "builddir", + bin_path=bin_path ) - if fc not in fc_options: - raise ValueError( - f"Fortran compiler {fc} not supported. Fortran compile must be " - + f"[{', '.join(str(value) for value in fc_options)}]." - ) - - # set FC environment variable - os.environ["FC"] = fc - - -def meson_build( - dir_path: str = "..", - libdir: str = "bin", -): - set_compiler_environment_variable() - is_windows = sys.platform.lower() == "win32" - with set_directory(dir_path): - cmd = ( - "meson setup builddir " - + f"--bindir={os.path.abspath(libdir)} " - + f"--libdir={os.path.abspath(libdir)} " - + "--prefix=" - ) - if is_windows: - cmd += "%CD%" - else: - cmd += "$(pwd)" - if pl.Path("builddir").is_dir(): - cmd += " --wipe" - print(f"setup meson\nrunning...\n {cmd}") - sp.run(cmd, shell=True, check=True) - - cmd = "meson install -C builddir" - print(f"build and install with meson\nrunning...\n {cmd}") - sp.run(cmd, shell=True, check=True) - - -def test_create_dirs(): - pths = [os.path.join("..", "bin"), os.path.join("temp")] - - for pth in pths: - create_dir(pth) - - return - - -def test_meson_build(): - meson_build() if __name__ == "__main__": - test_create_dirs() - test_meson_build() + parser = argparse.ArgumentParser("Rebuild local development version of MODFLOW 6") + parser.add_argument("-p", "--path", help="path to bin directory") + args = parser.parse_args() + bin_path = Path(args.path).resolve() if args.path else _bin_path + test_meson_build(bin_path) diff --git a/autotest/common_regression.py b/autotest/common_regression.py deleted file mode 100644 index 65951f5b6d5..00000000000 --- a/autotest/common_regression.py +++ /dev/null @@ -1,168 +0,0 @@ -import os -import sys - -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - - -def get_home_dir(): - # determine if CI run - is_CI = "CI" in os.environ - - home = os.path.expanduser("~") - - if is_CI: - if sys.platform.lower() == "win32": - home = os.path.normpath(os.path.join(os.getcwd(), "..", "..")) - else: - cwd_pth = os.getcwd() - - # convert current working directory to a list - cwd_list = cwd_pth.split(sep=os.path.sep) - - # add leading path separator back into list - for idx, pth in enumerate(cwd_list): - if len(pth) < 1: - cwd_list[idx] = os.path.sep - if pth.endswith(":") and sys.platform.lower() == "win32": - cwd_list[idx] += os.path.sep - - ipos = 0 - for idx, s in enumerate(cwd_list): - if s.lower().startswith("modflow6"): - ipos = idx - break - - home = os.path.join(*cwd_list[:ipos]) - - print(f"HOME: {home}") - - return home - - -def set_mf6_regression(): - mf6_regression = True - for arg in sys.argv: - if arg.lower() in ("--original_regression", "-oreg"): - mf6_regression = False - break - return mf6_regression - - -def is_directory_available(example_basedir): - available = False - if example_basedir is not None: - available = os.path.isdir(example_basedir) - if not available: - print(f'"{example_basedir}" does not exist') - print(f"no need to run {os.path.basename(__file__)}") - return available - - -def get_example_basedir(home, find_dir, subdir=None): - example_basedir = None - for root, dirs, files in os.walk(home): - for d in dirs: - if d == find_dir or d == find_dir + ".git": - example_basedir = os.path.join(root, d) - if subdir is not None: - example_basedir = os.path.join(example_basedir, subdir) - break - if example_basedir is not None: - example_basedir = os.path.abspath(example_basedir) - print(f"Example base directory: {example_basedir}") - break - return example_basedir - - -def get_example_dirs(example_basedir, exclude, prefix="test", find_sim=True): - example_dirs = [ - d - for d in os.listdir(example_basedir) - if prefix in d and d not in exclude - ] - - # make sure mfsim.nam is present in each directory - if find_sim: - remove_dirs = [] - # add_dirs = [] - for temp_dir in example_dirs: - epth = os.path.join(example_basedir, temp_dir) - fpth = os.path.join(epth, "mfsim.nam") - if not os.path.isfile(fpth): - remove_dirs.append(temp_dir) - # for sub_dir in ("mf6gwf", "mf6gwt"): - # tpth = os.path.join(epth, sub_dir) - # fpth = os.path.join(tpth, "mfsim.nam") - # if os.path.isfile(fpth): - # add_dirs.append(os.path.join(temp_dir, sub_dir)) - - for remove_dir in remove_dirs: - example_dirs.remove(remove_dir) - - # example_dirs += add_dirs - - # sort in numerical order for case sensitive os - example_dirs = sorted( - example_dirs, key=lambda v: (v.upper(), v[0].islower()) - ) - - return example_dirs - - -def get_select_dirs(select_dirs, dirs): - found_dirs = [] - for d in select_dirs: - if d.endswith("*"): - for test_dir in dirs: - if test_dir.startswith(d.replace("*", "")): - found_dirs.append(test_dir) - elif d.endswith("+"): - dd = d.replace("+", "") - for test_dir in dirs: - sorted_list = sorted([dd, test_dir], reverse=True) - if sorted_list[0] == test_dir: - found_dirs.append(test_dir) - elif d.endswith("-"): - dd = d.replace("-", "") - for test_dir in dirs: - sorted_list = sorted([dd, test_dir]) - if sorted_list[0] == test_dir or dd in sorted_list[0]: - found_dirs.append(test_dir) - else: - if d in dirs: - found_dirs.append(d) - - return found_dirs - - -def get_select_packages(select_packages, exdir, dirs): - found_dirs = [] - for d in dirs: - pth = os.path.join(exdir, d) - namefiles = pymake.get_namefiles(pth) - ftypes = [] - for namefile in namefiles: - ftype = pymake.get_mf6_ftypes(namefile, select_packages) - if ftype not in ftypes: - ftypes += ftype - if len(ftypes) > 0: - ftypes = [item.upper() for item in ftypes] - for pak in select_packages: - if pak in ftypes: - found_dirs.append(d) - break - return found_dirs diff --git a/autotest/conftest.py b/autotest/conftest.py new file mode 100644 index 00000000000..30459ee73df --- /dev/null +++ b/autotest/conftest.py @@ -0,0 +1,104 @@ +from pathlib import Path +from typing import List + +import pytest +from modflow_devtools.executables import build_default_exe_dict, Executables +from modflow_devtools.misc import is_in_ci + +_project_root_path = Path(__file__).parent.parent + + +# import modflow-devtools fixtures and configuration + +pytest_plugins = ["modflow_devtools.fixtures"] + + +# utilities + +def get_project_root_path() -> Path: + return _project_root_path + + +def get_bin_path() -> Path: + return _project_root_path / "bin" + + +def should_compare(test: str, comparisons: dict, exes: Executables): + if test in comparisons.keys(): + version = Executables.get_version(path=exes.mf6) + print(f"MODFLOW 6 development version='{version}'") + version = Executables.get_version(path=exes.mf6_regression) + print(f"MODFLOW 6 regression version='{version}'") + if version in comparisons[test]: + print( + f"Test {test} does not run with versions {comparisons[test]}" + ) + print( + f"Skipping regression test of sim {test} because the version is {version}" + ) + return False + return True + + +# fixtures + +@pytest.fixture(scope="session") +def bin_path() -> Path: + return get_bin_path() + + +@pytest.fixture(scope="session") +def targets(bin_path) -> Executables: + return Executables(**build_default_exe_dict(bin_path)) + + +@pytest.fixture(autouse=True) +def close_plot(request): + import matplotlib.pyplot as plt + yield + + # automatically close any plots on teardown + # plots only shown if requested via CLI flag, + # figures are available, and we're not in CI + show = request.config.getoption("--show-plots") + if len(plt.get_fignums()) > 0 and not is_in_ci() and show: + plt.show() + else: + plt.close("all") + + +@pytest.fixture +def original_regression(request) -> bool: + oreg = request.config.getoption("--original-regression") + return oreg + + +@pytest.fixture +def selected_models(request) -> List[str]: + models = request.config.getoption("--model", None) + return models if models else [] + + +@pytest.fixture +def selected_packages(request) -> List[str]: + packages = request.config.getoption("--package", None) + return packages if packages else [] + + +# pytest configuration hooks + +def pytest_addoption(parser): + parser.addoption( + "--show-plots", + action="store_true", + default=False, + help="Show any figure windows created by test cases. (Useful to display plots for visual inspection, " + "but automated tests should probably also check patch collections or figure & axis properties.)", + ) + + parser.addoption( + "--original-regression", + action="store_true", + default=False, + help="TODO" + ) diff --git a/autotest/scripts/cross_section_functions.py b/autotest/cross_section_functions.py similarity index 100% rename from autotest/scripts/cross_section_functions.py rename to autotest/cross_section_functions.py diff --git a/autotest/disu_util.py b/autotest/disu_util.py deleted file mode 100644 index 041e728622b..00000000000 --- a/autotest/disu_util.py +++ /dev/null @@ -1,101 +0,0 @@ -import numpy as np - - -def get_disu_kwargs(nlay, nrow, ncol, delr, delc, tp, botm): - """ - Simple utility for creating args needed to construct - a disu package - - """ - - def get_nn(k, i, j): - return k * nrow * ncol + i * ncol + j - - nodes = nlay * nrow * ncol - iac = np.zeros((nodes), dtype=int) - ja = [] - area = np.zeros((nodes), dtype=float) - top = np.zeros((nodes), dtype=float) - bot = np.zeros((nodes), dtype=float) - ihc = [] - cl12 = [] - hwva = [] - for k in range(nlay): - for i in range(nrow): - for j in range(ncol): - # diagonal - n = get_nn(k, i, j) - ja.append(n) - iac[n] += 1 - area[n] = delr[i] * delc[j] - ihc.append(n + 1) - cl12.append(n + 1) - hwva.append(n + 1) - if k == 0: - top[n] = tp - else: - top[n] = botm[k - 1] - bot[n] = botm[k] - # up - if k > 0: - ja.append(get_nn(k - 1, i, j)) - iac[n] += 1 - ihc.append(0) - dz = botm[k - 1] - botm[k] - cl12.append(0.5 * dz) - hwva.append(delr[i] * delc[j]) - # back - if i > 0: - ja.append(get_nn(k, i - 1, j)) - iac[n] += 1 - ihc.append(1) - cl12.append(0.5 * delc[i]) - hwva.append(delr[j]) - # left - if j > 0: - ja.append(get_nn(k, i, j - 1)) - iac[n] += 1 - ihc.append(1) - cl12.append(0.5 * delr[j]) - hwva.append(delc[i]) - # right - if j < ncol - 1: - ja.append(get_nn(k, i, j + 1)) - iac[n] += 1 - ihc.append(1) - cl12.append(0.5 * delr[j]) - hwva.append(delc[i]) - # front - if i < nrow - 1: - ja.append(get_nn(k, i + 1, j)) - iac[n] += 1 - ihc.append(1) - cl12.append(0.5 * delc[i]) - hwva.append(delr[j]) - # bottom - if k < nlay - 1: - ja.append(get_nn(k + 1, i, j)) - iac[n] += 1 - ihc.append(0) - if k == 0: - dz = tp - botm[k] - else: - dz = botm[k - 1] - botm[k] - cl12.append(0.5 * dz) - hwva.append(delr[i] * delc[j]) - ja = np.array(ja, dtype=int) - nja = ja.shape[0] - hwva = np.array(hwva, dtype=float) - kw = {} - kw["nodes"] = nodes - kw["nja"] = nja - kw["nvert"] = None - kw["top"] = top - kw["bot"] = bot - kw["area"] = area - kw["iac"] = iac - kw["ja"] = ja - kw["ihc"] = ihc - kw["cl12"] = cl12 - kw["hwva"] = hwva - return kw diff --git a/autotest/framework.py b/autotest/framework.py deleted file mode 100644 index c37bced6250..00000000000 --- a/autotest/framework.py +++ /dev/null @@ -1,100 +0,0 @@ -import os -import sys - -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - - -def running_on_CI(): - return "TRAVIS" in os.environ or "CI" in os.environ - - -def set_teardown_test(): - teardown = True - for idx, arg in enumerate(sys.argv): - if arg.lower() == "--keep": - teardown = False - return teardown - - -class testing_framework(object): - def __init__(self): - return - - def build_mf6_models(self, build_function, idx, exdir): - """ - Build base and regression MODFLOW 6 models - - Parameters - ---------- - build_function : function - user defined function that builds a base model and optionally - builds a regression model. If a regression model is not built - then None must be returned from the function for the regression - model. - idx : int - counter that corresponds to exdir entry - exdir : str - path to regression model files - """ - base, regression = build_function(idx, exdir) - base.write_simulation() - if regression is not None: - if isinstance(regression, flopy.mf6.MFSimulation): - regression.write_simulation() - else: - regression.write_input() - - def build_mf6_models_legacy(self, build_function, idx, exdir): - """ - Build base and regression for older MODFLOW 6 models - - Parameters - ---------- - build_function : function - user defined function that builds a base model and optionally - builds a regression model. If a regression model is not built - then None must be returned from the function for the regression - model. - idx : int - counter that corresponds to exdir entry - exdir : str - path to regression model files - """ - base, regression = build_function(idx, exdir) - base.write_simulation() - if regression is not None: - regression.write_input() - - def run_mf6(self, sim): - """ - Run the MODFLOW 6 simulation and compare to existing head file or - appropriate MODFLOW-2005, MODFLOW-NWT, MODFLOW-USG, or MODFLOW-LGR run. - - Parameters - ---------- - sim : Simulation object - MODFLOW 6 autotest simulation object that runs the base and - regression models, compares the results, and tears down the - test if successful. - """ - print(os.getcwd()) - sim.set_model(sim.name, testModel=False) - sim.run() - sim.compare() - if sim.exfunc is not None: - sim.exfunc(sim) - sim.teardown() diff --git a/autotest/get_exes.py b/autotest/get_exes.py index 7530f31ca3f..1d912ef0614 100644 --- a/autotest/get_exes.py +++ b/autotest/get_exes.py @@ -1,119 +1,93 @@ -# Get executables - -import os -import shutil +import argparse +from pathlib import Path +from tempfile import TemporaryDirectory +from warnings import warn +import flopy +import pytest from flaky import flaky -import pymake - -from build_exes import meson_build -from framework import running_on_CI - -if running_on_CI(): - print("running on CI environment") - os.environ["PYMAKE_DOUBLE"] = "1" - -# path to rebuilt executables for previous versions of MODFLOW -rebuilt_bindir = os.path.join("..", "bin", "rebuilt") - -if not os.path.exists(rebuilt_bindir): - os.makedirs(rebuilt_bindir) - -# paths to downloaded for previous versions of MODFLOW -downloaded_bindir = os.path.join("..", "bin", "downloaded") - -if not os.path.exists(downloaded_bindir): - os.makedirs(downloaded_bindir) - - -mfexe_pth = "temp/mfexes" +from modflow_devtools.build import meson_build +from modflow_devtools.download import download_and_unzip, get_release +from modflow_devtools.misc import get_ostag -# use the line below to set fortran compiler using environmental variables -# os.environ["FC"] = "gfortran" +from conftest import get_project_root_path -# some flags to check for errors in the code -# add -Werror for compilation to terminate if errors are found -strict_flags = ( - "-Wtabs -Wline-truncation -Wunused-label " - "-Wunused-variable -pedantic -std=f2008 " - "-Wcharacter-truncation" -) +_repository = "MODFLOW-USGS/modflow6" +_project_root_path = get_project_root_path() +_bin_path = _project_root_path / "bin" -def get_compiler_envvar(fc): - env_var = os.environ.get("FC") - if env_var is not None: - if env_var != fc: - fc = env_var - return fc +def get_asset_name(asset: dict) -> str: + ostag = get_ostag() + name = asset["name"] + if "win" in ostag: + return name + else: + prefix = name.rpartition('_')[0] + prefix += f"_{ostag}" + return f"{prefix}.zip" -def create_dir(pth): - # create pth directory - print(f"creating... {os.path.abspath(pth)}") - os.makedirs(pth, exist_ok=True) +@pytest.fixture +def rebuilt_bin_path() -> Path: + return _bin_path / "rebuilt" - msg = f"could not create... {os.path.abspath(pth)}" - assert os.path.exists(pth), msg - -def rebuild_mf6_release(): - target = "mf6" - download_pth = os.path.join("temp") - target_dict = pymake.usgs_program_data.get_target(target) - - pymake.download_and_unzip( - target_dict["url"], - pth=download_pth, - verbose=True, - ) - - # update IDEVELOP MODE in the release - srcpth = os.path.join( - download_pth, target_dict["dirname"], target_dict["srcdir"] - ) - fpth = os.path.join(srcpth, "Utilities", "version.f90") - with open(fpth) as f: - lines = f.read().splitlines() - assert len(lines) > 0, f"could not update {srcpth}" - - f = open(fpth, "w") - for line in lines: - tag = "IDEVELOPMODE = 0" - if tag in line: - line = line.replace(tag, "IDEVELOPMODE = 1") - f.write(f"{line}\n") - f.close() - - # build release source files with Meson - root_path = os.path.join(download_pth, target_dict["dirname"]) - meson_build(dir_path=root_path, libdir=os.path.abspath(rebuilt_bindir)) - - -def test_create_dirs(): - pths = [os.path.join("..", "bin"), os.path.join("temp")] - - for pth in pths: - create_dir(pth) +@pytest.fixture +def downloaded_bin_path() -> Path: + return _bin_path / "downloaded" @flaky(max_runs=3) -def test_getmfexes(verify=True): - pymake.getmfexes(mfexe_pth, verify=verify) - for target in os.listdir(mfexe_pth): - srcpth = os.path.join(mfexe_pth, target) - if os.path.isfile(srcpth): - dstpth = os.path.join(downloaded_bindir, target) - print(f"copying {srcpth} -> {dstpth}") - shutil.copy(srcpth, dstpth) +def test_rebuild_release(rebuilt_bin_path: Path): + print(f"Rebuilding and installing last release to: {rebuilt_bin_path}") + release = get_release(_repository) + assets = release["assets"] + asset = next(iter([a for a in assets if a["name"] == get_asset_name(a)]), None) + if not asset: + warn(f"Couldn't find asset for OS {get_ostag()}, available assets:\n{assets}") + + with TemporaryDirectory() as td: + download_path = Path(td) + download_and_unzip( + asset["browser_download_url"], + path=download_path, + verbose=True, + ) + + # update IDEVELOPMODE + source_files_path = download_path / asset["name"].replace(".zip", "") / "src" + version_file_path = source_files_path / "Utilities" / "version.f90" + with open(version_file_path) as f: + lines = f.read().splitlines() + assert len(lines) > 0, f"File is empty: {source_files_path}" + with open(version_file_path, "w") as f: + for line in lines: + tag = "IDEVELOPMODE = 0" + if tag in line: + line = line.replace(tag, "IDEVELOPMODE = 1") + f.write(f"{line}\n") + + # rebuild with Meson + meson_build( + project_path=source_files_path.parent, + build_path=download_path / "builddir", + bin_path=rebuilt_bin_path + ) @flaky(max_runs=3) -def test_rebuild_mf6_release(): - rebuild_mf6_release() +def test_get_executables(downloaded_bin_path: Path): + print(f"Installing MODFLOW-related executables to: {downloaded_bin_path}") + downloaded_bin_path.mkdir(exist_ok=True, parents=True) + flopy.utils.get_modflow(str(downloaded_bin_path)) if __name__ == "__main__": - test_create_dirs() - test_getmfexes(verify=False) - test_rebuild_mf6_release() + parser = argparse.ArgumentParser("Prepare external binaries needed for MODFLOW 6 testing") + parser.add_argument("-p", "--path", help="path to bin directory") + args = parser.parse_args() + bin_path = Path(args.path).resolve() if args.path else _bin_path + + test_get_executables(bin_path / "downloaded") + test_rebuild_release(bin_path / "rebuilt") diff --git a/autotest/harness.py b/autotest/harness.py new file mode 100644 index 00000000000..78f412d05c0 --- /dev/null +++ b/autotest/harness.py @@ -0,0 +1,1710 @@ +import os +import shutil +import sys +import time +from pathlib import Path +from os import PathLike + +import flopy +import numpy as np +from flopy.utils.compare import compare_heads +from modflow_devtools.misc import is_in_ci + +ignore_ext = ( + ".hds", + ".hed", + ".bud", + ".cbb", + ".cbc", + ".ddn", + ".ucn", + ".glo", + ".lst", + ".list", + ".gwv", + ".mv", + ".out", +) + + +class TestHarness: + def build(self, build_function, idx, exdir): + """ + Build base and regression MODFLOW 6 models + Parameters + ---------- + build_function : function + user defined function that builds a base model and optionally + builds a regression model. If a regression model is not built + then None must be returned from the function for the regression + model. + idx : int + counter that corresponds to exdir entry + exdir : str + path to regression model files + """ + base, regression = build_function(idx, exdir) + base.write_simulation() + if regression is not None: + if isinstance(regression, flopy.mf6.MFSimulation): + regression.write_simulation() + else: + regression.write_input() + + def run(self, config, workspace): + """ + Run the MODFLOW 6 test and compare to existing head file or + MODFLOW-2005, MODFLOW-NWT, MODFLOW-USG, or MODFLOW-LGR run. + Parameters + ---------- + config : TestConfig object + Modflow 6 test configuration object that runs the base and + regression models, compares the results, and tears down the + test if successful. + workspace : Pathlike + The test workspace + """ + config.set_model(workspace, testModel=False) + config.run() + config.compare() + if config.exfunc is not None: + config.exfunc(config) + + +class TestConfig: + # tell pytest this isn't a test class, don't collect it + __test__ = False + + sfmt = "{:25s} - {}" + extdict = { + "hds": "head", + "hed": "head", + "bhd": "head", + "ucn": "concentration", + "cbc": "cell-by-cell", + } + + def __init__( + self, + name, + exes, + exfunc=None, + htol=None, + pdtol=None, + rclose=None, + idxsim=None, + cmp_verbose=True, + require_failure=None, + api_func=None, + mf6_regression=False, + make_comparison=True, + ): + self.targets = exes.as_dict() + + for idx, arg in enumerate(sys.argv): + if arg[2:].lower() in list(self.targets.keys()): + key = arg[2:].lower() + exe0 = self.targets[key] + exe = os.path.join(os.path.dirname(exe0), sys.argv[idx + 1]) + msg = ( + f"replacing {key} executable " + + f'"{self.targets[key]}" with ' + + f'"{exe}".' + ) + print(msg) + self.targets[key] = exe + + msg = self.sfmt.format("Initializing test", name) + print(msg) + self.name = name + self.exfunc = exfunc + self.simpath = None + self.inpt = None + self.outp = None + self.coutp = None + self.api_func = api_func + self.mf6_regression = mf6_regression + self.make_comparison = make_comparison + self.action = None + + # set htol for comparisons + if htol is None: + htol = 0.001 + else: + msg = self.sfmt.format("User specified comparison htol", htol) + print(msg) + + self.htol = htol + + # set pdtol for comparisons + if pdtol is None: + pdtol = 0.001 + else: + msg = self.sfmt.format( + "User specified percent difference comparison pdtol", pdtol + ) + print(msg) + + self.pdtol = pdtol + + # set rclose for comparisons + if rclose is None: + rclose = 0.001 + else: + msg = self.sfmt.format( + "User specified percent difference comparison rclose", rclose + ) + print(msg) + + self.rclose = rclose + + # set index for multi-simulation comparisons + self.idxsim = idxsim + + # set compare verbosity + self.cmp_verbose = cmp_verbose + + # set allow failure + self.require_failure = require_failure + + self.success = False + + # set is_ci + self.is_CI = is_in_ci() + + def __repr__(self): + return self.name + + def set_model(self, pth, testModel=True): + """ + Set paths to MODFLOW 6 model and associated comparison test + """ + # make sure this is a valid path + if not os.path.isdir(pth): + assert False, f"{pth} is not a valid directory" + + self.simpath = pth + + # get MODFLOW 6 output file names + fpth = os.path.join(pth, "mfsim.nam") + mf6inp, mf6outp = get_mf6_files(fpth) + self.outp = mf6outp + + # determine comparison model + self.setup_comparison(pth, pth, testModel=testModel) + # if self.mf6_regression: + # self.action = "mf6_regression" + # else: + # self.action = get_mf6_comparison(pth) + if self.action is not None: + if "mf6" in self.action or "mf6_regression" in self.action: + cinp, self.coutp = get_mf6_files(fpth) + + def setup(self, src, dst): + msg = self.sfmt.format("Setup test", self.name) + self.originpath = src + self.simpath = dst + self.inpt, self.outp = setup_mf6(src=src, dst=dst) + time.sleep(0.5) + self.setup_comparison(src, dst) + + def setup_comparison(self, src, dst, testModel=True): + + # evaluate if comparison should be made + if not self.make_comparison: + return + + # adjust htol if it is smaller than IMS outer_dvclose + dvclose = self._get_dvclose(dst) + if dvclose is not None: + dvclose *= 5.0 + if self.htol < dvclose: + self.htol = dvclose + + # get rclose to use with budget comparisons + rclose = self._get_rclose(dst) + if rclose is None: + rclose = 0.5 + else: + rclose *= 5.0 + self.rclose = rclose + + # Copy comparison simulations if available + if self.mf6_regression: + action = "mf6_regression" + pth = os.path.join(dst, action) + if os.path.isdir(pth): + shutil.rmtree(pth) + shutil.copytree(dst, pth) + elif testModel: + action = setup_mf6_comparison(src, dst) + else: + action = get_mf6_comparison(dst) + + self.action = action + + def run(self): + """ + Run the model and assert if the model terminated successfully + """ + msg = self.sfmt.format("Run test", self.name) + print(msg) + + # Set nam as namefile name without path + nam = None + + # run mf6 models + exe = self.targets["mf6"] + msg = self.sfmt.format("using executable", exe) + print(msg) + try: + success, buff = flopy.run_model( + exe, + nam, + model_ws=self.simpath, + silent=False, + report=True, + ) + msg = self.sfmt.format("MODFLOW 6 run", self.name) + if success: + print(msg) + else: + print(msg) + except: + msg = self.sfmt.format("MODFLOW 6 run", self.name) + print(msg) + success = False + + # set failure based on success and require_failure setting + if self.require_failure is None: + msg = "MODFLOW 6 model did not terminate normally" + if success: + failure = False + else: + failure = True + else: + if self.require_failure: + msg = "MODFLOW 6 model should have failed" + if not success: + failure = False + else: + failure = True + else: + msg = "MODFLOW 6 model should not have failed" + if success: + failure = False + else: + failure = True + + # print end of mfsim.lst to the screen + if failure and self.is_CI: + fpth = os.path.join(self.simpath, "mfsim.lst") + msg = self._get_mfsim_listing(fpth) + msg + + # test for failure + assert not failure, msg + + self.nam_cmp = None + if success: + if self.action is not None: + if self.action.lower() == "compare": + msg = self.sfmt.format("Comparison files", self.name) + print(msg) + else: + cpth = os.path.join(self.simpath, self.action) + key = self.action.lower().replace(".cmp", "") + exe = os.path.abspath(self.targets[key]) + msg = self.sfmt.format("comparison executable", exe) + print(msg) + if ( + "mf6" in key + or "libmf6" in key + or "mf6_regression" in key + ): + nam = None + else: + npth = get_namefiles(cpth)[0] + nam = os.path.basename(npth) + self.nam_cmp = nam + try: + if self.api_func is None: + success_cmp, buff = flopy.run_model( + exe, + nam, + model_ws=cpth, + silent=False, + report=True, + ) + else: + success_cmp, buff = self.api_func( + exe, self.idxsim, model_ws=cpth + ) + msg = self.sfmt.format( + "Comparison run", self.name + "/" + key + ) + print(msg) + + # print end of mfsim.lst to the screen + if "mf6" in key: + if not success and self.is_CI: + fpth = os.path.join(cpth, "mfsim.lst") + print(self._get_mfsim_listing(fpth)) + + except: + success_cmp = False + msg = self.sfmt.format( + "Comparison run", self.name + "/" + key + ) + print(msg) + + assert success_cmp, "Unsuccessful comparison run" + + def compare(self): + """ + Compare the model results + """ + self.success = True + + # evaluate if comparison should be made + if not self.make_comparison: + return + + msgall = "" + msg = self.sfmt.format("Comparison test", self.name) + print(msg) + + if self.action is not None: + cpth = os.path.join(self.simpath, self.action) + files_cmp = None + if self.action.lower() == "compare": + files_cmp = [] + files = os.listdir(cpth) + for file in files: + files_cmp.append(file) + elif "mf6" in self.action: + fpth = os.path.join(cpth, "mfsim.nam") + cinp, self.coutp = get_mf6_files(fpth) + + head_extensions = ( + "hds", + "hed", + "bhd", + "ahd", + "bin", + ) + if "mf6_regression" in self.action: + success, msgall = self._compare_heads( + msgall, + extensions=head_extensions, + ) + if not success: + self.success = False + # non-regression runs - for new features + else: + files1 = [] + files2 = [] + exfiles = [] + ipos = 0 + for file1 in self.outp: + ext = os.path.splitext(file1)[1][1:] + + if ext.lower() in head_extensions: + + # simulation file + pth = os.path.join(self.simpath, file1) + files1.append(pth) + + # look for an exclusion file + pth = os.path.join(self.simpath, file1 + ".ex") + if os.path.isfile(pth): + exfiles.append(pth) + else: + exfiles.append(None) + + # Check to see if there is a corresponding compare file + if files_cmp is not None: + + if file1 + ".cmp" in files_cmp: + # compare file + idx = files_cmp.index(file1 + ".cmp") + pth = os.path.join(cpth, files_cmp[idx]) + files2.append(pth) + txt = self.sfmt.format( + f"Comparison file {ipos + 1}", + os.path.basename(pth), + ) + print(txt) + else: + if self.coutp is not None: + for file2 in self.coutp: + ext = os.path.splitext(file2)[1][1:] + + if ext.lower() in head_extensions: + # simulation file + pth = os.path.join(cpth, file2) + files2.append(pth) + + else: + files2.append(None) + + if self.nam_cmp is None: + pth = None + else: + pth = os.path.join(cpth, self.nam_cmp) + + for ipos in range(len(files1)): + file1 = files1[ipos] + ext = os.path.splitext(file1)[1][1:].lower() + outfile = os.path.splitext(os.path.basename(file1))[0] + outfile = os.path.join( + self.simpath, outfile + "." + ext + ".cmp.out" + ) + if files2 is None: + file2 = None + else: + file2 = files2[ipos] + + # set exfile + exfile = None + if file2 is None: + if len(exfiles) > 0: + exfile = exfiles[ipos] + if exfile is not None: + txt = self.sfmt.format( + f"Exclusion file {ipos + 1}", + os.path.basename(exfile), + ) + print(txt) + + # make comparison + success_tst = compare_heads( + None, + pth, + precision="double", + text=self.extdict[ext], + outfile=outfile, + files1=file1, + files2=file2, + htol=self.htol, + difftol=True, + # Change to true to have list of all nodes exceeding htol + verbose=self.cmp_verbose, + exfile=exfile, + ) + msg = self.sfmt.format( + f"{self.extdict[ext]} comparison {ipos + 1}", + self.name, + ) + print(msg) + + if not success_tst: + self.success = False + msgall += msg + " ... FAILED\n" + + # compare concentrations + if "mf6_regression" in self.action: + success, msgall = self._compare_concentrations(msgall) + if not success: + self.success = False + + # compare cbc files + if "mf6_regression" in self.action: + cbc_extensions = ( + "cbc", + "bud", + ) + success, msgall = self._compare_budgets( + msgall, extensions=cbc_extensions + ) + if not success: + self.success = False + + assert self.success, msgall + + def _get_mfsim_listing(self, lst_pth): + """Get the tail of the mfsim.lst listing file""" + msg = "" + ilen = 100 + with open(lst_pth) as fp: + lines = fp.read().splitlines() + msg = "\n" + 79 * "-" + "\n" + if len(lines) > ilen: + i0 = -100 + else: + i0 = 0 + for line in lines[i0:]: + if len(line) > 0: + msg += f"{line}\n" + msg += 79 * "-" + "\n\n" + return msg + + def _get_dvclose(self, dir_pth): + """Get outer_dvclose value from MODFLOW 6 ims file""" + dvclose = None + files = os.listdir(dir_pth) + for file_name in files: + pth = os.path.join(dir_pth, file_name) + if os.path.isfile(pth): + if file_name.lower().endswith(".ims"): + with open(pth) as f: + lines = f.read().splitlines() + for line in lines: + if "outer_dvclose" in line.lower(): + v = float(line.split()[1]) + if dvclose is None: + dvclose = v + else: + if v > dvclose: + dvclose = v + break + + return dvclose + + def _get_rclose(self, dir_pth): + """Get inner_rclose value from MODFLOW 6 ims file""" + rclose = None + files = os.listdir(dir_pth) + for file_name in files: + pth = os.path.join(dir_pth, file_name) + if os.path.isfile(pth): + if file_name.lower().endswith(".ims"): + with open(pth) as f: + lines = f.read().splitlines() + for line in lines: + if "inner_rclose" in line.lower(): + v = float(line.split()[1]) + if rclose is None: + rclose = v + else: + if v > rclose: + rclose = v + break + + return rclose + + def _regression_files(self, extensions): + if isinstance(extensions, str): + extensions = [extensions] + files = os.listdir(self.simpath) + files0 = [] + files1 = [] + for file_name in files: + fpth0 = os.path.join(self.simpath, file_name) + if os.path.isfile(fpth0): + for extension in extensions: + if file_name.lower().endswith(extension): + files0.append(fpth0) + fpth1 = os.path.join( + self.simpath, "mf6_regression", file_name + ) + files1.append(fpth1) + break + return files0, files1 + + def _compare_heads(self, msgall, extensions="hds"): + if isinstance(extensions, str): + extensions = [extensions] + success = True + files0, files1 = self._regression_files(extensions) + extension = "hds" + ipos = 0 + for idx, (fpth0, fpth1) in enumerate(zip(files0, files1)): + outfile = os.path.splitext(os.path.basename(fpth0))[0] + outfile = os.path.join( + self.simpath, outfile + f".{extension}.cmp.out" + ) + success_tst = compare_heads( + None, + None, + precision="double", + htol=self.htol, + text=self.extdict[extension], + outfile=outfile, + files1=fpth0, + files2=fpth1, + verbose=self.cmp_verbose, + ) + msg = self.sfmt.format( + f"{self.extdict[extension]} comparison {ipos + 1}", + f"{self.name} ({os.path.basename(fpth0)})", + ) + ipos += 1 + print(msg) + + if not success_tst: + success = False + msgall += msg + " ... FAILED\n" + + return success, msgall + + def _compare_concentrations(self, msgall, extensions="ucn"): + if isinstance(extensions, str): + extensions = [extensions] + success = True + files0, files1 = self._regression_files(extensions) + extension = "ucn" + ipos = 0 + for idx, (fpth0, fpth1) in enumerate(zip(files0, files1)): + outfile = os.path.splitext(os.path.basename(fpth0))[0] + outfile = os.path.join( + self.simpath, outfile + f".{extension}.cmp.out" + ) + success_tst = compare_heads( + None, + None, + precision="double", + htol=self.htol, + text=self.extdict[extension], + outfile=outfile, + files1=fpth0, + files2=fpth1, + verbose=self.cmp_verbose, + ) + msg = self.sfmt.format( + f"{self.extdict[extension]} comparison {ipos + 1}", + f"{self.name} ({os.path.basename(fpth0)})", + ) + ipos += 1 + print(msg) + + if not success_tst: + success = False + msgall += msg + " ... FAILED\n" + + return success, msgall + + def _compare_budgets(self, msgall, extensions="cbc"): + if isinstance(extensions, str): + extensions = [extensions] + success = True + files0, files1 = self._regression_files(extensions) + extension = "cbc" + ipos = 0 + for idx, (fpth0, fpth1) in enumerate(zip(files0, files1)): + if os.stat(fpth0).st_size * os.stat(fpth0).st_size == 0: + continue + outfile = os.path.splitext(os.path.basename(fpth0))[0] + outfile = os.path.join( + self.simpath, outfile + f".{extension}.cmp.out" + ) + fcmp = open(outfile, "w") + + # open the files + cbc0 = flopy.utils.CellBudgetFile( + fpth0, precision="double", verbose=self.cmp_verbose + ) + cbc1 = flopy.utils.CellBudgetFile( + fpth1, precision="double", verbose=self.cmp_verbose + ) + + # build list of cbc data to retrieve + avail0 = cbc0.get_unique_record_names() + avail1 = cbc1.get_unique_record_names() + avail0 = [t.decode().strip() for t in avail0] + avail1 = [t.decode().strip() for t in avail1] + + # initialize list for storing totals for each budget term terms + cbc_keys0 = [] + cbc_keys1 = [] + for t in avail0: + t1 = t + if t not in avail1: + # check if RCHA or EVTA is available and use that instead + # should be able to remove this once v6.3.0 is released + if t[:-1] in avail1: + t1 = t[:-1] + else: + raise Exception(f"Could not find {t} in {fpth1}") + cbc_keys0.append(t) + cbc_keys1.append(t1) + + # get list of times and kstpkper + kk = cbc0.get_kstpkper() + times = cbc0.get_times() + + # process data + success_tst = True + for key, key1 in zip(cbc_keys0, cbc_keys1): + for idx, (k, t) in enumerate(zip(kk, times)): + v0 = cbc0.get_data(kstpkper=k, text=key)[0] + v1 = cbc1.get_data(kstpkper=k, text=key1)[0] + if v0.dtype.names is not None: + v0 = v0["q"] + v1 = v1["q"] + # skip empty vectors + if v0.size < 1: + continue + vmin = self.rclose + if vmin < 1e-6: + vmin = 1e-6 + vmin_tol = 5.0 * vmin + idx = (abs(v0) > vmin) & (abs(v1) > vmin) + diff = np.zeros(v0.shape, dtype=v0.dtype) + diff[idx] = abs(v0[idx] - v1[idx]) + diffmax = diff.max() + indices = np.where(diff == diffmax)[0] + if diffmax > vmin_tol: + success_tst = False + msg = ( + f"{os.path.basename(fpth0)} - " + + f"{key:16s} " + + f"difference ({diffmax:10.4g}) " + + f"> {self.pdtol:10.4g} " + + f"at {indices.size} nodes " + + f" [first location ({indices[0] + 1})] " + + f"at time {t} " + ) + fcmp.write(f"{msg}\n") + if self.cmp_verbose: + print(msg) + + msg = self.sfmt.format( + f"{self.extdict[extension]} comparison {ipos + 1}", + f"{self.name} ({os.path.basename(fpth0)})", + ) + ipos += 1 + print(msg) + + fcmp.close() + + if not success_tst: + success = False + msgall += msg + " ... FAILED\n" + + return success, msgall + + +def model_setup(namefile, dst, remove_existing=True, extrafiles=None): + """Setup MODFLOW-based model files for autotests. + + Parameters + ---------- + namefile : str + MODFLOW-based model name file. + dst : str + destination path for comparison model or file(s) + remove_existing : bool + boolean indicating if an existing comparision model or file(s) should + be replaced (default is True) + extrafiles : str or list of str + list of extra files to include in the comparision + + Returns + ------- + + """ + # Construct src pth from namefile or lgr file + src = os.path.dirname(namefile) + + # Create the destination folder, if required + create_dir = False + if os.path.exists(dst): + if remove_existing: + print("Removing folder " + dst) + shutil.rmtree(dst) + create_dir = True + else: + create_dir = True + if create_dir: + os.mkdir(dst) + + # determine if a namefile is a lgr control file - get individual + # name files out of the lgr control file + namefiles = [namefile] + ext = os.path.splitext(namefile)[1] + if ".lgr" in ext.lower(): + lines = [line.rstrip("\n") for line in open(namefile)] + for line in lines: + if len(line) < 1: + continue + if line[0] == "#": + continue + t = line.split() + if ".nam" in t[0].lower(): + fpth = os.path.join(src, t[0]) + namefiles.append(fpth) + + # Make list of files to copy + files2copy = [] + for fpth in namefiles: + files2copy.append(os.path.basename(fpth)) + ext = os.path.splitext(fpth)[1] + # copy additional files contained in the name file and + # associated package files + if ext.lower() == ".nam": + fname = os.path.abspath(fpth) + files2copy = files2copy + get_input_files(fname) + + if extrafiles is not None: + if isinstance(extrafiles, str): + extrafiles = [extrafiles] + for fl in extrafiles: + files2copy.append(os.path.basename(fl)) + + # Copy the files + for f in files2copy: + srcf = os.path.join(src, f) + dstf = os.path.join(dst, f) + + # Check to see if dstf is going into a subfolder, and create that + # subfolder if it doesn't exist + sf = os.path.dirname(dstf) + if not os.path.isdir(sf): + os.makedirs(sf) + + # Now copy the file + if os.path.exists(srcf): + print("Copy file '" + srcf + "' -> '" + dstf + "'") + shutil.copy(srcf, dstf) + else: + print(srcf + " does not exist") + + return + + +def setup_comparison(namefile, dst, remove_existing=True): + """Setup a comparison model or comparision file(s) for a MODFLOW-based + model. + + Parameters + ---------- + namefile : str + MODFLOW-based model name file. + dst : str + destination path for comparison model or file(s) + remove_existing : bool + boolean indicating if an existing comparision model or file(s) should + be replaced (default is True) + + + Returns + ------- + + """ + # Construct src pth from namefile + src = os.path.dirname(namefile) + action = None + for root, dirs, files in os.walk(src): + dl = [d.lower() for d in dirs] + if any(".cmp" in s for s in dl): + idx = None + for jdx, d in enumerate(dl): + if ".cmp" in d: + idx = jdx + break + if idx is not None: + if "mf2005.cmp" in dl[idx] or "mf2005" in dl[idx]: + action = dirs[idx] + elif "mfnwt.cmp" in dl[idx] or "mfnwt" in dl[idx]: + action = dirs[idx] + elif "mfusg.cmp" in dl[idx] or "mfusg" in dl[idx]: + action = dirs[idx] + elif "mf6.cmp" in dl[idx] or "mf6" in dl[idx]: + action = dirs[idx] + elif "libmf6.cmp" in dl[idx] or "libmf6" in dl[idx]: + action = dirs[idx] + else: + action = dirs[idx] + break + if action is not None: + dst = os.path.join(dst, f"{action}") + if not os.path.isdir(dst): + try: + os.mkdir(dst) + except: + print("Could not make " + dst) + # clean directory + else: + print(f"cleaning...{dst}") + for root, dirs, files in os.walk(dst): + for f in files: + tpth = os.path.join(root, f) + print(f" removing...{tpth}") + os.remove(tpth) + for d in dirs: + tdir = os.path.join(root, d) + print(f" removing...{tdir}") + shutil.rmtree(tdir) + # copy files + cmppth = os.path.join(src, action) + files = os.listdir(cmppth) + files2copy = [] + if action.lower() == ".cmp": + for file in files: + if ".cmp" in os.path.splitext(file)[1].lower(): + files2copy.append(os.path.join(cmppth, file)) + for srcf in files2copy: + f = os.path.basename(srcf) + dstf = os.path.join(dst, f) + # Now copy the file + if os.path.exists(srcf): + print("Copy file '" + srcf + "' -> '" + dstf + "'") + shutil.copy(srcf, dstf) + else: + print(srcf + " does not exist") + else: + for file in files: + if ".nam" in os.path.splitext(file)[1].lower(): + files2copy.append( + os.path.join(cmppth, os.path.basename(file)) + ) + nf = os.path.join(src, action, os.path.basename(file)) + model_setup(nf, dst, remove_existing=remove_existing) + break + + return action + + +def teardown(src): + """Teardown a autotest directory. + + Parameters + ---------- + src : str + autotest directory to teardown + + Returns + ------- + + """ + if os.path.exists(src): + print("Removing folder " + src) + shutil.rmtree(src) + return + + +def get_input_files(namefile): + """Return a list of all the input files in this model. + + Parameters + ---------- + namefile : str + path to a MODFLOW-based model name file + + Returns + ------- + filelist : list + list of MODFLOW-based model input files + + """ + srcdir = os.path.dirname(namefile) + filelist = [] + fname = os.path.join(srcdir, namefile) + with open(fname, "r") as f: + lines = f.readlines() + + for line in lines: + ll = line.strip().split() + if len(ll) < 2: + continue + if line.strip()[0] in ["#", "!"]: + continue + ext = os.path.splitext(ll[2])[1] + if ext.lower() not in ignore_ext: + if len(ll) > 3: + if "replace" in ll[3].lower(): + continue + filelist.append(ll[2]) + + # Now go through every file and look for other files to copy, + # such as 'OPEN/CLOSE'. If found, then add that file to the + # list of files to copy. + otherfiles = [] + for fname in filelist: + fname = os.path.join(srcdir, fname) + try: + f = open(fname, "r") + for line in f: + + # Skip invalid lines + ll = line.strip().split() + if len(ll) < 2: + continue + if line.strip()[0] in ["#", "!"]: + continue + + if "OPEN/CLOSE" in line.upper(): + for i, s in enumerate(ll): + if "OPEN/CLOSE" in s.upper(): + stmp = ll[i + 1] + stmp = stmp.replace('"', "") + stmp = stmp.replace("'", "") + otherfiles.append(stmp) + break + except: + print(fname + " does not exist") + + filelist = filelist + otherfiles + + return filelist + + +def get_namefiles(pth, exclude=None): + """Search through a path (pth) for all .nam files. + + Parameters + ---------- + pth : str + path to model files + exclude : str or lst + File or list of files to exclude from the search (default is None) + + Returns + ------- + namefiles : lst + List of namefiles with paths + + """ + namefiles = [] + for root, _, files in os.walk(pth): + namefiles += [ + os.path.join(root, file) for file in files if file.endswith(".nam") + ] + if exclude is not None: + if isinstance(exclude, str): + exclude = [exclude] + exclude = [e.lower() for e in exclude] + pop_list = [] + for namefile in namefiles: + for e in exclude: + if e in namefile.lower(): + pop_list.append(namefile) + for e in pop_list: + namefiles.remove(e) + + return namefiles + + +def get_entries_from_namefile(namefile, ftype=None, unit=None, extension=None): + """Get entries from a namefile. Can select using FTYPE, UNIT, or file + extension. + + Parameters + ---------- + namefile : str + path to a MODFLOW-based model name file + ftype : str + package type + unit : int + file unit number + extension : str + file extension + + Returns + ------- + entries : list of tuples + list of tuples containing FTYPE, UNIT, FNAME, STATUS for each + namefile entry that meets a user-specified value. + + """ + entries = [] + f = open(namefile, "r") + for line in f: + if line.strip() == "": + continue + if line[0] == "#": + continue + ll = line.strip().split() + if len(ll) < 3: + continue + status = "UNKNOWN" + if len(ll) > 3: + status = ll[3].upper() + if ftype is not None: + if ftype.upper() == ll[0].upper(): + filename = os.path.join(os.path.split(namefile)[0], ll[2]) + entries.append((filename, ll[0], ll[1], status)) + elif unit is not None: + if int(unit) == int(ll[1]): + filename = os.path.join(os.path.split(namefile)[0], ll[2]) + entries.append((filename, ll[0], ll[1], status)) + elif extension is not None: + filename = os.path.join(os.path.split(namefile)[0], ll[2]) + ext = os.path.splitext(filename)[1] + if len(ext) > 0: + if ext[0] == ".": + ext = ext[1:] + if extension.lower() == ext.lower(): + entries.append((filename, ll[0], ll[1], status)) + f.close() + if len(entries) < 1: + entries.append((None, None, None, None)) + return entries + + +def get_sim_name(namefiles, rootpth=None): + """Get simulation name. + + Parameters + ---------- + namefiles : str or list of strings + path(s) to MODFLOW-based model name files + rootpth : str + optional root directory path (default is None) + + Returns + ------- + simname : list + list of namefiles without the file extension + + """ + if isinstance(namefiles, str): + namefiles = [namefiles] + sim_name = [] + for namefile in namefiles: + t = namefile.split(os.sep) + if rootpth is None: + idx = -1 + else: + idx = t.index(os.path.split(rootpth)[1]) + + # build dst with everything after the rootpth and before + # the namefile file name. + dst = "" + if idx < len(t): + for d in t[idx + 1 : -1]: + dst += f"{d}_" + + # add namefile basename without extension + dst += t[-1].replace(".nam", "") + sim_name.append(dst) + + return sim_name + + +# modflow 6 readers and copiers +def setup_mf6( + src, dst, mfnamefile="mfsim.nam", extrafiles=None, remove_existing=True +): + """Copy all of the MODFLOW 6 input files from the src directory to the dst + directory. + + Parameters + ---------- + src : src + directory path with original MODFLOW 6 input files + dst : str + directory path that original MODFLOW 6 input files will be copied to + mfnamefile : str + optional MODFLOW 6 simulation name file (default is mfsim.nam) + extrafiles : bool + boolean indicating if extra files should be included (default is None) + remove_existing : bool + boolean indicating if existing file in dst should be removed (default + is True) + + Returns + ------- + mf6inp : list + list of MODFLOW 6 input files + mf6outp : list + list of MODFLOW 6 output files + + """ + + # Create the destination folder + create_dir = False + if os.path.exists(dst): + if remove_existing: + print("Removing folder " + dst) + shutil.rmtree(dst) + create_dir = True + else: + create_dir = True + if create_dir: + os.makedirs(dst) + + # Make list of files to copy + fname = os.path.join(src, mfnamefile) + fname = os.path.abspath(fname) + mf6inp, mf6outp = get_mf6_files(fname) + files2copy = [mfnamefile] + mf6inp + + # determine if there are any .ex files + exinp = [] + for f in mf6outp: + ext = os.path.splitext(f)[1] + if ext.lower() == ".hds": + pth = os.path.join(src, f + ".ex") + if os.path.isfile(pth): + exinp.append(f + ".ex") + if len(exinp) > 0: + files2copy += exinp + if extrafiles is not None: + files2copy += extrafiles + + # Copy the files + for f in files2copy: + srcf = os.path.join(src, f) + dstf = os.path.join(dst, f) + + # Check to see if dstf is going into a subfolder, and create that + # subfolder if it doesn't exist + sf = os.path.dirname(dstf) + if not os.path.isdir(sf): + try: + os.mkdir(sf) + except: + print("Could not make " + sf) + + # Now copy the file + if os.path.exists(srcf): + print("Copy file '" + srcf + "' -> '" + dstf + "'") + shutil.copy(srcf, dstf) + else: + print(srcf + " does not exist") + + return mf6inp, mf6outp + + +def get_mf6_comparison(src): + """Determine comparison type for MODFLOW 6 simulation. + + Parameters + ---------- + src : str + directory path to search for comparison types + + Returns + ------- + action : str + comparison type + + """ + action = None + # Possible comparison - the order matters + optcomp = ( + "compare", + ".cmp", + "mf2005", + "mf2005.cmp", + "mfnwt", + "mfnwt.cmp", + "mfusg", + "mfusg.cmp", + "mflgr", + "mflgr.cmp", + "libmf6", + "libmf6.cmp", + "mf6", + "mf6.cmp", + ) + # Construct src pth from namefile + action = None + for _, dirs, _ in os.walk(src): + dl = [d.lower() for d in dirs] + for oc in optcomp: + if any(oc in s for s in dl): + action = oc + break + return action + + +def setup_mf6_comparison(src, dst, remove_existing=True): + """Setup comparision for MODFLOW 6 simulation. + + Parameters + ---------- + src : src + directory path with original MODFLOW 6 input files + dst : str + directory path that original MODFLOW 6 input files will be copied to + remove_existing : bool + boolean indicating if existing file in dst should be removed (default + is True) + + Returns + ------- + action : str + comparison type + + """ + # get the type of comparison to use (compare, mf2005, etc.) + action = get_mf6_comparison(src) + + if action is not None: + dst = os.path.join(dst, f"{action}") + if not os.path.isdir(dst): + try: + os.mkdir(dst) + except: + print("Could not make " + dst) + # clean directory + else: + print(f"cleaning...{dst}") + for root, dirs, files in os.walk(dst): + for f in files: + tpth = os.path.join(root, f) + print(f" removing...{tpth}") + os.remove(tpth) + for d in dirs: + tdir = os.path.join(root, d) + print(f" removing...{tdir}") + shutil.rmtree(tdir) + # copy files + cmppth = os.path.join(src, action) + files = os.listdir(cmppth) + files2copy = [] + if action.lower() == "compare" or action.lower() == ".cmp": + for file in files: + if ".cmp" in os.path.splitext(file)[1].lower(): + files2copy.append(os.path.join(cmppth, file)) + for srcf in files2copy: + f = os.path.basename(srcf) + dstf = os.path.join(dst, f) + # Now copy the file + if os.path.exists(srcf): + print("Copy file '" + srcf + "' -> '" + dstf + "'") + shutil.copy(srcf, dstf) + else: + print(srcf + " does not exist") + else: + if "mf6" in action.lower(): + for file in files: + if "mfsim.nam" in file.lower(): + srcf = os.path.join(cmppth, os.path.basename(file)) + files2copy.append(srcf) + srcdir = os.path.join(src, action) + setup_mf6(srcdir, dst, remove_existing=remove_existing) + break + else: + for file in files: + if ".nam" in os.path.splitext(file)[1].lower(): + srcf = os.path.join(cmppth, os.path.basename(file)) + files2copy.append(srcf) + nf = os.path.join(src, action, os.path.basename(file)) + model_setup(nf, dst, remove_existing=remove_existing) + break + + return action + + +def get_mf6_nper(tdisfile): + """Return the number of stress periods in the MODFLOW 6 model. + + Parameters + ---------- + tdisfile : str + path to the TDIS file + + Returns + ------- + nper : int + number of stress periods in the simulation + + """ + with open(tdisfile, "r") as f: + lines = f.readlines() + line = [line for line in lines if "NPER" in line.upper()][0] + nper = line.strip().split()[1] + return nper + + +def get_mf6_mshape(disfile): + """Return the shape of the MODFLOW 6 model. + + Parameters + ---------- + disfile : str + path to a MODFLOW 6 discretization file + + Returns + ------- + mshape : tuple + tuple with the shape of the MODFLOW 6 model. + + """ + with open(disfile, "r") as f: + lines = f.readlines() + + d = {} + for line in lines: + + # Skip over blank and commented lines + ll = line.strip().split() + if len(ll) < 2: + continue + if line.strip()[0] in ["#", "!"]: + continue + + for key in ["NODES", "NCPL", "NLAY", "NROW", "NCOL"]: + if ll[0].upper() in key: + d[key] = int(ll[1]) + + if "NODES" in d: + mshape = (d["NODES"],) + elif "NCPL" in d: + mshape = (d["NLAY"], d["NCPL"]) + elif "NLAY" in d: + mshape = (d["NLAY"], d["NROW"], d["NCOL"]) + else: + print(d) + raise Exception("Could not determine model shape") + return mshape + + +def get_mf6_files(mfnamefile): + """Return a list of all the MODFLOW 6 input and output files in this model. + + Parameters + ---------- + mfnamefile : str + path to the MODFLOW 6 simulation name file + + Returns + ------- + filelist : list + list of MODFLOW 6 input files in a simulation + outplist : list + list of MODFLOW 6 output files in a simulation + + """ + + srcdir = os.path.dirname(mfnamefile) + filelist = [] + outplist = [] + + filekeys = ["TDIS6", "GWF6", "GWT", "GWF6-GWF6", "GWF-GWT", "IMS6"] + namefilekeys = ["GWF6", "GWT"] + namefiles = [] + + with open(mfnamefile) as f: + + # Read line and skip comments + lines = f.readlines() + + for line in lines: + + # Skip over blank and commented lines + ll = line.strip().split() + if len(ll) < 2: + continue + if line.strip()[0] in ["#", "!"]: + continue + + for key in filekeys: + if key in ll[0].upper(): + fname = ll[1] + filelist.append(fname) + + for key in namefilekeys: + if key in ll[0].upper(): + fname = ll[1] + namefiles.append(fname) + + # Go through name files and get files + for namefile in namefiles: + fname = os.path.join(srcdir, namefile) + with open(fname, "r") as f: + lines = f.readlines() + insideblock = False + + for line in lines: + ll = line.upper().strip().split() + if len(ll) < 2: + continue + if ll[0] in "BEGIN" and ll[1] in "PACKAGES": + insideblock = True + continue + if ll[0] in "END" and ll[1] in "PACKAGES": + insideblock = False + + if insideblock: + ll = line.strip().split() + if len(ll) < 2: + continue + if line.strip()[0] in ["#", "!"]: + continue + filelist.append(ll[1]) + + # Recursively go through every file and look for other files to copy, + # such as 'OPEN/CLOSE' and 'TIMESERIESFILE'. If found, then + # add that file to the list of files to copy. + flist = filelist + # olist = outplist + while True: + olist = [] + flist, olist = _get_mf6_external_files(srcdir, olist, flist) + # add to filelist + if len(flist) > 0: + filelist = filelist + flist + # add to outplist + if len(olist) > 0: + outplist = outplist + olist + # terminate loop if no additional files + # if len(flist) < 1 and len(olist) < 1: + if len(flist) < 1: + break + + return filelist, outplist + + +def _get_mf6_external_files(srcdir, outplist, files): + """Get list of external files in a MODFLOW 6 simulation. + + Parameters + ---------- + srcdir : str + path to a directory containing a MODFLOW 6 simulation + outplist : list + list of output files in a MODFLOW 6 simulation + files : list + list of MODFLOW 6 name files + + Returns + ------- + + """ + extfiles = [] + + for fname in files: + fname = os.path.join(srcdir, fname) + try: + f = open(fname, "r") + for line in f: + + # Skip invalid lines + ll = line.strip().split() + if len(ll) < 2: + continue + if line.strip()[0] in ["#", "!"]: + continue + + if "OPEN/CLOSE" in line.upper(): + for i, s in enumerate(ll): + if s.upper() == "OPEN/CLOSE": + stmp = ll[i + 1] + stmp = stmp.replace('"', "") + stmp = stmp.replace("'", "") + extfiles.append(stmp) + break + + if "TS6" in line.upper(): + for i, s in enumerate(ll): + if s.upper() == "FILEIN": + stmp = ll[i + 1] + stmp = stmp.replace('"', "") + stmp = stmp.replace("'", "") + extfiles.append(stmp) + break + + if "TAS6" in line.upper(): + for i, s in enumerate(ll): + if s.upper() == "FILEIN": + stmp = ll[i + 1] + stmp = stmp.replace('"', "") + stmp = stmp.replace("'", "") + extfiles.append(stmp) + break + + if "OBS6" in line.upper(): + for i, s in enumerate(ll): + if s.upper() == "FILEIN": + stmp = ll[i + 1] + stmp = stmp.replace('"', "") + stmp = stmp.replace("'", "") + extfiles.append(stmp) + break + + if "EXTERNAL" in line.upper(): + for i, s in enumerate(ll): + if s.upper() == "EXTERNAL": + stmp = ll[i + 1] + stmp = stmp.replace('"', "") + stmp = stmp.replace("'", "") + extfiles.append(stmp) + break + + if "FILE" in line.upper(): + for i, s in enumerate(ll): + if s.upper() == "FILEIN": + stmp = ll[i + 1] + stmp = stmp.replace('"', "") + stmp = stmp.replace("'", "") + extfiles.append(stmp) + break + + if "FILE" in line.upper(): + for i, s in enumerate(ll): + if s.upper() == "FILEOUT": + stmp = ll[i + 1] + stmp = stmp.replace('"', "") + stmp = stmp.replace("'", "") + outplist.append(stmp) + break + + except: + print("could not get a list of external mf6 files") + + return extfiles, outplist + + +def get_mf6_ftypes(namefile, ftypekeys): + """Return a list of FTYPES that are in the name file and in ftypekeys. + + Parameters + ---------- + namefile : str + path to a MODFLOW 6 name file + ftypekeys : list + list of desired FTYPEs + + Returns + ------- + ftypes : list + list of FTYPES that match ftypekeys in namefile + + """ + with open(namefile, "r") as f: + lines = f.readlines() + + ftypes = [] + for line in lines: + + # Skip over blank and commented lines + ll = line.strip().split() + if len(ll) < 2: + continue + if line.strip()[0] in ["#", "!"]: + continue + + for key in ftypekeys: + if ll[0].upper() in key: + ftypes.append(ll[0]) + + return ftypes + + +def get_mf6_blockdata(f, blockstr): + """Return list with all non comments between start and end of block + specified by blockstr. + + Parameters + ---------- + f : file object + open file object + blockstr : str + name of block to search + + Returns + ------- + data : list + list of data in specified block + + """ + data = [] + + # find beginning of block + for line in f: + if line[0] != "#": + t = line.split() + if t[0].lower() == "begin" and t[1].lower() == blockstr.lower(): + break + for line in f: + if line[0] != "#": + t = line.split() + if t[0].lower() == "end" and t[1].lower() == blockstr.lower(): + break + else: + data.append(line.rstrip()) + return data diff --git a/autotest/pyproject.toml b/autotest/pyproject.toml index dbb4477760a..a3bce3133ee 100644 --- a/autotest/pyproject.toml +++ b/autotest/pyproject.toml @@ -5,4 +5,4 @@ build-backend = "setuptools.build_meta" [tool.black] line-length = 79 -target_version = ["py37"] +target_version = ["py37"] \ No newline at end of file diff --git a/autotest/pytest.ini b/autotest/pytest.ini index d718b03a102..4344bef1d56 100644 --- a/autotest/pytest.ini +++ b/autotest/pytest.ini @@ -1,3 +1,17 @@ [pytest] +python_files = + test_*.py + *_test*.py markers = - developmode: tests that should only run with IDEVELOPMODE = 1 \ No newline at end of file + meta: tests run by other tests (e.g. testing fixtures) + slow: tests taking more than a few seconds to complete + repo: tests using models loaded from an external repository + large: tests that rely on an external repository for data + regression: comparing results from different versions + distribution: tests for release & distribution scripts + gwf: tests for groundwater flow models + gwt: tests for groundwater transport models + ats: tests for adaptive time step utility plugin + aux: tests for auxiliary variables plugin + lak: tests for flow lake plugin + maw: tests for multi-aquifer well plugin \ No newline at end of file diff --git a/autotest/simulation.py b/autotest/simulation.py deleted file mode 100644 index d9eb0b7cdb6..00000000000 --- a/autotest/simulation.py +++ /dev/null @@ -1,804 +0,0 @@ -import os -import shutil -import sys -import time - -import numpy as np - -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -import targets -from framework import running_on_CI, set_teardown_test - -sfmt = "{:25s} - {}" -extdict = { - "hds": "head", - "hed": "head", - "bhd": "head", - "ucn": "concentration", - "cbc": "cell-by-cell", -} - - -class Simulation(object): - def __init__( - self, - name, - exfunc=None, - exe_dict=None, - htol=None, - pdtol=None, - rclose=None, - idxsim=None, - cmp_verbose=True, - require_failure=None, - api_func=None, - mf6_regression=False, - make_comparison=True, - ): - teardown_test = set_teardown_test() - for idx, arg in enumerate(sys.argv): - if arg[2:].lower() in list(targets.target_dict.keys()): - key = arg[2:].lower() - exe0 = targets.target_dict[key] - exe = os.path.join(os.path.dirname(exe0), sys.argv[idx + 1]) - msg = ( - f"replacing {key} executable " - + f'"{targets.target_dict[key]}" with ' - + f'"{exe}".' - ) - print(msg) - targets.target_dict[key] = exe - - if exe_dict is not None: - if not isinstance(exe_dict, dict): - msg = "exe_dict must be a dictionary" - assert False, msg - keys = list(targets.target_dict.keys()) - for key, value in exe_dict.items(): - if key in keys: - exe0 = targets.target_dict[key] - exe = os.path.join(os.path.dirname(exe0), value) - msg = ( - f"replacing {key} executable " - + f'"{targets.target_dict[key]}" with ' - + f'"{exe}".' - ) - print(msg) - targets.target_dict[key] = exe - - msg = sfmt.format("Initializing test", name) - print(msg) - self.name = name - self.exfunc = exfunc - self.simpath = None - self.inpt = None - self.outp = None - self.coutp = None - self.api_func = api_func - self.mf6_regression = mf6_regression - self.make_comparison = make_comparison - self.action = None - - # set htol for comparisons - if htol is None: - htol = 0.001 - else: - msg = sfmt.format("User specified comparison htol", htol) - print(msg) - - self.htol = htol - - # set pdtol for comparisons - if pdtol is None: - pdtol = 0.001 - else: - msg = sfmt.format( - "User specified percent difference comparison pdtol", pdtol - ) - print(msg) - - self.pdtol = pdtol - - # set rclose for comparisons - if rclose is None: - rclose = 0.001 - else: - msg = sfmt.format( - "User specified percent difference comparison rclose", rclose - ) - print(msg) - - self.rclose = rclose - - # set index for multi-simulation comparisons - self.idxsim = idxsim - - # set compare verbosity - self.cmp_verbose = cmp_verbose - - # set allow failure - self.require_failure = require_failure - - self.teardown_test = teardown_test - self.success = False - - # set is_ci - self.is_CI = running_on_CI() - - return - - def __repr__(self): - return self.name - - def set_model(self, pth, testModel=True): - """ - Set paths to MODFLOW 6 model and associated comparison test - """ - # make sure this is a valid path - if not os.path.isdir(pth): - assert False, f"{pth} is not a valid directory" - - self.simpath = pth - - # get MODFLOW 6 output file names - fpth = os.path.join(pth, "mfsim.nam") - mf6inp, mf6outp = pymake.get_mf6_files(fpth) - self.outp = mf6outp - - # determine comparison model - self.setup_comparison(pth, pth, testModel=testModel) - # if self.mf6_regression: - # self.action = "mf6-regression" - # else: - # self.action = pymake.get_mf6_comparison(pth) - if self.action is not None: - if "mf6" in self.action or "mf6-regression" in self.action: - cinp, self.coutp = pymake.get_mf6_files(fpth) - - def setup(self, src, dst): - msg = sfmt.format("Setup test", self.name) - print(msg) - self.originpath = src - self.simpath = dst - # write message - print( - "running pymake.setup_mf6 from " - + f"{os.path.abspath(os.getcwd())}" - ) - try: - self.inpt, self.outp = pymake.setup_mf6(src=src, dst=dst) - print("waiting...") - time.sleep(0.5) - success = True - except: - success = False - print(f"source: {src}") - print(f"destination: {dst}") - assert success, "did not run pymake.setup_mf6" - - if success: - self.setup_comparison(src, dst) - - return - - def setup_comparison(self, src, dst, testModel=True): - - # evaluate if comparison should be made - if not self.make_comparison: - return - - # adjust htol if it is smaller than IMS outer_dvclose - dvclose = self._get_dvclose(dst) - if dvclose is not None: - dvclose *= 5.0 - if self.htol < dvclose: - self.htol = dvclose - - # get rclose to use with budget comparisons - rclose = self._get_rclose(dst) - if rclose is None: - rclose = 0.5 - else: - rclose *= 5.0 - self.rclose = rclose - - # Copy comparison simulations if available - if self.mf6_regression: - action = "mf6-regression" - pth = os.path.join(dst, action) - if os.path.isdir(pth): - shutil.rmtree(pth) - shutil.copytree(dst, pth) - elif testModel: - action = pymake.setup_mf6_comparison( - src, dst, remove_existing=self.teardown_test - ) - else: - action = pymake.get_mf6_comparison(dst) - - self.action = action - - return - - def run(self): - """ - Run the model and assert if the model terminated successfully - """ - msg = sfmt.format("Run test", self.name) - print(msg) - - # Set nam as namefile name without path - nam = None - - # run mf6 models - target, ext = os.path.splitext(targets.program) - exe = os.path.abspath(targets.target_dict[target]) - msg = sfmt.format("using executable", exe) - print(msg) - try: - success, buff = flopy.run_model( - exe, - nam, - model_ws=self.simpath, - silent=False, - report=True, - ) - msg = sfmt.format("MODFLOW 6 run", self.name) - if success: - print(msg) - else: - print(msg) - except: - msg = sfmt.format("MODFLOW 6 run", self.name) - print(msg) - success = False - - # set failure based on success and require_failure setting - if self.require_failure is None: - msg = "MODFLOW 6 model did not terminate normally" - if success: - failure = False - else: - failure = True - else: - if self.require_failure: - msg = "MODFLOW 6 model should have failed" - if not success: - failure = False - else: - failure = True - else: - msg = "MODFLOW 6 model should not have failed" - if success: - failure = False - else: - failure = True - - # print end of mfsim.lst to the screen - if failure and self.is_CI: - fpth = os.path.join(self.simpath, "mfsim.lst") - msg = self._get_mfsim_listing(fpth) + msg - - # test for failure - assert not failure, msg - - self.nam_cmp = None - if success: - if self.action is not None: - if self.action.lower() == "compare": - msg = sfmt.format("Comparison files", self.name) - print(msg) - else: - cpth = os.path.join(self.simpath, self.action) - key = self.action.lower().replace(".cmp", "") - exe = os.path.abspath(targets.target_dict[key]) - msg = sfmt.format("comparison executable", exe) - print(msg) - if ( - "mf6" in key - or "libmf6" in key - or "mf6-regression" in key - ): - nam = None - else: - npth = pymake.get_namefiles(cpth)[0] - nam = os.path.basename(npth) - self.nam_cmp = nam - try: - if self.api_func is None: - success_cmp, buff = flopy.run_model( - exe, - nam, - model_ws=cpth, - silent=False, - report=True, - ) - else: - success_cmp, buff = self.api_func( - exe, self.idxsim, model_ws=cpth - ) - msg = sfmt.format( - "Comparison run", self.name + "/" + key - ) - print(msg) - - # print end of mfsim.lst to the screen - if "mf6" in key: - if not success and self.is_CI: - fpth = os.path.join(cpth, "mfsim.lst") - print(self._get_mfsim_listing(fpth)) - - except: - success_cmp = False - msg = sfmt.format( - "Comparison run", self.name + "/" + key - ) - print(msg) - - assert success_cmp, "Unsuccessful comparison run" - - return - - def compare(self): - """ - Compare the model results - - """ - self.success = True - - # evaluate if comparison should be made - if not self.make_comparison: - return - - msgall = "" - msg = sfmt.format("Comparison test", self.name) - print(msg) - - if self.action is not None: - cpth = os.path.join(self.simpath, self.action) - files_cmp = None - if self.action.lower() == "compare": - files_cmp = [] - files = os.listdir(cpth) - for file in files: - files_cmp.append(file) - elif "mf6" in self.action: - fpth = os.path.join(cpth, "mfsim.nam") - cinp, self.coutp = pymake.get_mf6_files(fpth) - - head_extensions = ( - "hds", - "hed", - "bhd", - "ahd", - "bin", - ) - if "mf6-regression" in self.action: - success, msgall = self._compare_heads( - msgall, - extensions=head_extensions, - ) - if not success: - self.success = False - # non-regression runs - for new features - else: - files1 = [] - files2 = [] - exfiles = [] - ipos = 0 - for file1 in self.outp: - ext = os.path.splitext(file1)[1][1:] - - if ext.lower() in head_extensions: - - # simulation file - pth = os.path.join(self.simpath, file1) - files1.append(pth) - - # look for an exclusion file - pth = os.path.join(self.simpath, file1 + ".ex") - if os.path.isfile(pth): - exfiles.append(pth) - else: - exfiles.append(None) - - # Check to see if there is a corresponding compare file - if files_cmp is not None: - - if file1 + ".cmp" in files_cmp: - # compare file - idx = files_cmp.index(file1 + ".cmp") - pth = os.path.join(cpth, files_cmp[idx]) - files2.append(pth) - txt = sfmt.format( - f"Comparison file {ipos + 1}", - os.path.basename(pth), - ) - print(txt) - else: - if self.coutp is not None: - for file2 in self.coutp: - ext = os.path.splitext(file2)[1][1:] - - if ext.lower() in head_extensions: - # simulation file - pth = os.path.join(cpth, file2) - files2.append(pth) - - else: - files2.append(None) - - if self.nam_cmp is None: - pth = None - else: - pth = os.path.join(cpth, self.nam_cmp) - - for ipos in range(len(files1)): - file1 = files1[ipos] - ext = os.path.splitext(file1)[1][1:].lower() - outfile = os.path.splitext(os.path.basename(file1))[0] - outfile = os.path.join( - self.simpath, outfile + "." + ext + ".cmp.out" - ) - if files2 is None: - file2 = None - else: - file2 = files2[ipos] - - # set exfile - exfile = None - if file2 is None: - if len(exfiles) > 0: - exfile = exfiles[ipos] - if exfile is not None: - txt = sfmt.format( - f"Exclusion file {ipos + 1}", - os.path.basename(exfile), - ) - print(txt) - - # make comparison - success_tst = pymake.compare_heads( - None, - pth, - precision="double", - text=extdict[ext], - outfile=outfile, - files1=file1, - files2=file2, - htol=self.htol, - difftol=True, - # Change to true to have list of all nodes exceeding htol - verbose=self.cmp_verbose, - exfile=exfile, - ) - msg = sfmt.format( - f"{extdict[ext]} comparison {ipos + 1}", - self.name, - ) - print(msg) - - if not success_tst: - self.success = False - msgall += msg + " ... FAILED\n" - - # compare concentrations - if "mf6-regression" in self.action: - success, msgall = self._compare_concentrations(msgall) - if not success: - self.success = False - - # compare cbc files - if "mf6-regression" in self.action: - cbc_extensions = ( - "cbc", - "bud", - ) - success, msgall = self._compare_budgets( - msgall, extensions=cbc_extensions - ) - if not success: - self.success = False - - assert self.success, msgall - return - - def teardown(self): - """ - Remove the example folder - - """ - if self.success: - if self.teardown_test: - msg = sfmt.format("Teardown test", self.name) - print(msg) - - # wait to delete on windows - if sys.platform.lower() == "win32": - time.sleep(3) - - try: - shutil.rmtree(self.simpath) - success = True - except: - print("Could not remove test " + self.name) - success = False - assert success - else: - print("Retaining test files") - return - - def _get_mfsim_listing(self, lst_pth): - """Get the tail of the mfsim.lst listing file""" - msg = "" - ilen = 100 - with open(lst_pth) as fp: - lines = fp.read().splitlines() - msg = "\n" + 79 * "-" + "\n" - if len(lines) > ilen: - i0 = -100 - else: - i0 = 0 - for line in lines[i0:]: - if len(line) > 0: - msg += f"{line}\n" - msg += 79 * "-" + "\n\n" - return msg - - def _get_dvclose(self, dir_pth): - """Get outer_dvclose value from MODFLOW 6 ims file""" - dvclose = None - files = os.listdir(dir_pth) - for file_name in files: - pth = os.path.join(dir_pth, file_name) - if os.path.isfile(pth): - if file_name.lower().endswith(".ims"): - with open(pth) as f: - lines = f.read().splitlines() - for line in lines: - if "outer_dvclose" in line.lower(): - v = float(line.split()[1]) - if dvclose is None: - dvclose = v - else: - if v > dvclose: - dvclose = v - break - - return dvclose - - def _get_rclose(self, dir_pth): - """Get inner_rclose value from MODFLOW 6 ims file""" - rclose = None - files = os.listdir(dir_pth) - for file_name in files: - pth = os.path.join(dir_pth, file_name) - if os.path.isfile(pth): - if file_name.lower().endswith(".ims"): - with open(pth) as f: - lines = f.read().splitlines() - for line in lines: - if "inner_rclose" in line.lower(): - v = float(line.split()[1]) - if rclose is None: - rclose = v - else: - if v > rclose: - rclose = v - break - - return rclose - - def _regression_files(self, extensions): - if isinstance(extensions, str): - extensions = [extensions] - files = os.listdir(self.simpath) - files0 = [] - files1 = [] - for file_name in files: - fpth0 = os.path.join(self.simpath, file_name) - if os.path.isfile(fpth0): - for extension in extensions: - if file_name.lower().endswith(extension): - files0.append(fpth0) - fpth1 = os.path.join( - self.simpath, "mf6-regression", file_name - ) - files1.append(fpth1) - break - return files0, files1 - - def _compare_heads(self, msgall, extensions="hds"): - if isinstance(extensions, str): - extensions = [extensions] - success = True - files0, files1 = self._regression_files(extensions) - extension = "hds" - ipos = 0 - for idx, (fpth0, fpth1) in enumerate(zip(files0, files1)): - outfile = os.path.splitext(os.path.basename(fpth0))[0] - outfile = os.path.join( - self.simpath, outfile + f".{extension}.cmp.out" - ) - success_tst = pymake.compare_heads( - None, - None, - precision="double", - htol=self.htol, - text=extdict[extension], - outfile=outfile, - files1=fpth0, - files2=fpth1, - verbose=self.cmp_verbose, - ) - msg = sfmt.format( - f"{extdict[extension]} comparison {ipos + 1}", - f"{self.name} ({os.path.basename(fpth0)})", - ) - ipos += 1 - print(msg) - - if not success_tst: - success = False - msgall += msg + " ... FAILED\n" - - return success, msgall - - def _compare_concentrations(self, msgall, extensions="ucn"): - if isinstance(extensions, str): - extensions = [extensions] - success = True - files0, files1 = self._regression_files(extensions) - extension = "ucn" - ipos = 0 - for idx, (fpth0, fpth1) in enumerate(zip(files0, files1)): - outfile = os.path.splitext(os.path.basename(fpth0))[0] - outfile = os.path.join( - self.simpath, outfile + f".{extension}.cmp.out" - ) - success_tst = pymake.compare_heads( - None, - None, - precision="double", - htol=self.htol, - text=extdict[extension], - outfile=outfile, - files1=fpth0, - files2=fpth1, - verbose=self.cmp_verbose, - ) - msg = sfmt.format( - f"{extdict[extension]} comparison {ipos + 1}", - f"{self.name} ({os.path.basename(fpth0)})", - ) - ipos += 1 - print(msg) - - if not success_tst: - success = False - msgall += msg + " ... FAILED\n" - - return success, msgall - - def _compare_budgets(self, msgall, extensions="cbc"): - if isinstance(extensions, str): - extensions = [extensions] - success = True - files0, files1 = self._regression_files(extensions) - extension = "cbc" - ipos = 0 - for idx, (fpth0, fpth1) in enumerate(zip(files0, files1)): - if os.stat(fpth0).st_size * os.stat(fpth0).st_size == 0: - continue - outfile = os.path.splitext(os.path.basename(fpth0))[0] - outfile = os.path.join( - self.simpath, outfile + f".{extension}.cmp.out" - ) - fcmp = open(outfile, "w") - - # open the files - cbc0 = flopy.utils.CellBudgetFile( - fpth0, precision="double", verbose=self.cmp_verbose - ) - cbc1 = flopy.utils.CellBudgetFile( - fpth1, precision="double", verbose=self.cmp_verbose - ) - - # build list of cbc data to retrieve - avail0 = cbc0.get_unique_record_names() - avail1 = cbc1.get_unique_record_names() - avail0 = [t.decode().strip() for t in avail0] - avail1 = [t.decode().strip() for t in avail1] - - # initialize list for storing totals for each budget term terms - cbc_keys0 = [] - cbc_keys1 = [] - for t in avail0: - t1 = t - if t not in avail1: - # check if RCHA or EVTA is available and use that instead - # should be able to remove this once v6.3.0 is released - if t[:-1] in avail1: - t1 = t[:-1] - else: - raise Exception(f"Could not find {t} in {fpth1}") - cbc_keys0.append(t) - cbc_keys1.append(t1) - - # get list of times and kstpkper - kk = cbc0.get_kstpkper() - times = cbc0.get_times() - - # process data - success_tst = True - for key, key1 in zip(cbc_keys0, cbc_keys1): - for idx, (k, t) in enumerate(zip(kk, times)): - v0 = cbc0.get_data(kstpkper=k, text=key)[0] - v1 = cbc1.get_data(kstpkper=k, text=key1)[0] - if v0.dtype.names is not None: - v0 = v0["q"] - v1 = v1["q"] - # skip empty vectors - if v0.size < 1: - continue - vmin = self.rclose - if vmin < 1e-6: - vmin = 1e-6 - vmin_tol = 5.0 * vmin - idx = (abs(v0) > vmin) & (abs(v1) > vmin) - diff = np.zeros(v0.shape, dtype=v0.dtype) - diff[idx] = abs(v0[idx] - v1[idx]) - diffmax = diff.max() - indices = np.where(diff == diffmax)[0] - if diffmax > vmin_tol: - success_tst = False - msg = ( - f"{os.path.basename(fpth0)} - " - + f"{key:16s} " - + f"difference ({diffmax:10.4g}) " - + f"> {self.pdtol:10.4g} " - + f"at {indices.size} nodes " - + f" [first location ({indices[0] + 1})] " - + f"at time {t} " - ) - fcmp.write(f"{msg}\n") - if self.cmp_verbose: - print(msg) - - msg = sfmt.format( - f"{extdict[extension]} comparison {ipos + 1}", - f"{self.name} ({os.path.basename(fpth0)})", - ) - ipos += 1 - print(msg) - - fcmp.close() - - if not success_tst: - success = False - msgall += msg + " ... FAILED\n" - - return success, msgall - - -def api_return(success, model_ws): - """ - parse libmf6 stdout shared object file - """ - fpth = os.path.join(model_ws, "mfsim.stdout") - return success, open(fpth).readlines() diff --git a/autotest/targets.py b/autotest/targets.py deleted file mode 100644 index 9202f39a3bf..00000000000 --- a/autotest/targets.py +++ /dev/null @@ -1,98 +0,0 @@ -import os -import subprocess -import sys - -import flopy - - -def target_pth(target, pth): - exe_exists = flopy.which(target, path=pth) - # if target does not exist in specified path determine if it - # exists anywhere in the path - if exe_exists is None: - exe_exists = flopy.which(target) - if exe_exists is None: - exe_exists = os.path.abspath(os.path.join(pth, target)) - raise Exception(f"{exe_exists} does not exist or is not executable.") - return os.path.abspath(exe_exists) - - -target_ext = "" -target_so = ".so" -sysinfo = sys.platform.lower() -if sysinfo.lower() == "win32": - target_ext = ".exe" - target_so = ".dll" -elif sysinfo.lower() == "darwin": - target_so = ".dylib" - -# paths to executables for previous versions of MODFLOW -downloaded_bindir = os.path.join("..", "bin", "downloaded") -rebuilt_bindir = os.path.join("..", "bin", "rebuilt") - -# paths to MODFLOW 6 executable, source files, and example files -bindir = os.path.join("..", "bin") - -# create dictionary of valid executable targets for regression tests -target_dict = {} - -target = target_pth(f"mf2005dbl{target_ext}", downloaded_bindir) -target_dict["mf2005"] = target -target = target_pth(f"mfnwtdbl{target_ext}", downloaded_bindir) -target_dict["mfnwt"] = target -target = target_pth(f"mfusgdbl{target_ext}", downloaded_bindir) -target_dict["mfusg"] = target -target = target_pth(f"mflgrdbl{target_ext}", downloaded_bindir) -target_dict["mflgr"] = target -target = target_pth(f"mf2005{target_ext}", downloaded_bindir) -target_dict["mf2005s"] = target -target = target_pth(f"mt3dms{target_ext}", downloaded_bindir) -target_dict["mt3dms"] = target -target = target_pth(f"mf6{target_ext}", rebuilt_bindir) -target_dict["mf6-regression"] = target - -# create MODFLOW 6 target name and add to dictionary -program = f"mf6{target_ext}" -target = os.path.join(bindir, program) -target_dict["mf6"] = target - -# create MODFLOW 6 so/dll target name -tprog = f"libmf6{target_so}" -ttarg = os.path.join(bindir, tprog) -target_dict["libmf6"] = ttarg - -# add MODFLOW 5 to 6 converter to dictionary of valid executable targets -tprog = f"mf5to6{target_ext}" -ttarg = os.path.join(bindir, tprog) -target_dict["mf5to6"] = ttarg - -# add Zonebudget for 6 to dictionary of valid executable targets -tprog = f"zbud6{target_ext}" -ttarg = os.path.join(bindir, tprog) -target_dict["zbud6"] = ttarg - - -def run_exe(argv, ws="."): - buff = [] - proc = subprocess.Popen( - argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=ws - ) - result, error = proc.communicate() - if result is not None: - c = result.decode("utf-8") - c = c.rstrip("\r\n") - print(f"{c}") - buff.append(c) - - return proc.returncode, buff - - -def get_mf6_version(version="mf6"): - """Function to get MODFLOW 6 version number""" - exe = target_dict[version] - return_code, buff = run_exe((exe, "-v")) - if return_code == 0: - version = buff[0].split()[1] - else: - version = None - return version diff --git a/autotest/test_cli.py b/autotest/test_cli.py index a8e8f02aca6..2180b0e5a73 100644 --- a/autotest/test_cli.py +++ b/autotest/test_cli.py @@ -1,7 +1,8 @@ import subprocess -from pathlib import Path -_project_root_path = Path(__file__).parent.parent +from conftest import get_project_root_path + +_project_root_path = get_project_root_path() _bin_path = _project_root_path / "bin" diff --git a/autotest/test_examples.py b/autotest/test_examples.py new file mode 100644 index 00000000000..7700b63d51c --- /dev/null +++ b/autotest/test_examples.py @@ -0,0 +1,80 @@ +import os +from pathlib import Path +from os import PathLike +from typing import Tuple, List +from warnings import warn + +import pytest +from modflow_devtools.executables import Executables + +from conftest import should_compare, get_project_root_path +from harness import TestConfig + + +_excluded = [ + "ex-gwf-csub-p02c", + "ex-gwt-gwtgwt-mt3dms-p10", +] + + +@pytest.fixture +def examples_path() -> Path: + repos_path = os.environ.get("REPOS_PATH") + if repos_path is None: + warn("REPOS_PATH environment variable not set, defaulting to side-by-side with modflow6 repository") + repos_path = get_project_root_path().parent + return Path(repos_path) / "modflow6-examples" / "examples" + + +def is_nested(namfile_path: PathLike) -> bool: + p = Path(namfile_path) + if not p.is_file() or not p.name.endswith(".nam"): + raise ValueError(f"Expected namefile path, got {p}") + + return p.parent.parent.name != "examples" + + +@pytest.mark.slow +@pytest.mark.repo +@pytest.mark.regression +def test_example( + request, + function_tmpdir: Path, + examples_path: Path, + example_scenario: Tuple[str, List[Path]], + targets: Executables): + name, namfiles = example_scenario + if name in _excluded: + pytest.skip(f"Example '{name}' is excluded") + if is_nested(namfiles[0]): + pytest.skip(f"Example '{name}' is nested, nested model support is still in development") + + comparisons = { + "ex-gwf-capture": ("6.2.1",), + "ex-gwf-sagehen": ("6.2.1",), + "ex-gwf-sfr-p01b": ("6.2.1",), + "ex-gwf-nwt-p02a": ("6.2.1",), + "ex-gwf-lak-p01": ("6.2.1",), + "ex-gwf-lak-p02": ("6.2.1",), + "ex-gwf-nwt-p02b": ("6.2.1",), + "ex-gwf-advtidal": ("6.2.1",), + "ex-gwf-sfr-p01": ("6.2.1",), + "ex-gwf-lgr": ("6.2.2",), + "ex-gwt-rotate": ("6.2.2",), + "ex-gwt-gwtgwt-mt3dms-p10": ("6.3.0",), + } + + test = TestConfig( + name=name, + exes=targets, + mf6_regression=True, + cmp_verbose=False, + make_comparison=should_compare(request.node.name, comparisons, targets), + ) + + src = str(examples_path / name) + dst = os.path.join(str(function_tmpdir), name) + + test.setup(src, dst) + test.run() + test.compare() diff --git a/autotest/test_gwf.py b/autotest/test_gwf.py new file mode 100644 index 00000000000..1827afbc9ad --- /dev/null +++ b/autotest/test_gwf.py @@ -0,0 +1,29 @@ +from modflow_devtools.executables import Executables +from pytest_cases import parametrize_with_cases + +from harness import TestConfig +from test_gwf_maw04 import GwfMaw04Cases +from test_gwf_maw_cases import GwfMawCases + + +@parametrize_with_cases("case", cases=[ + GwfMawCases, + GwfMaw04Cases +]) +def test_gwf_models(case, targets: Executables): + data, sim, cmp, exfunc = case + sim.write_simulation() + if cmp: cmp.write_simulation() + + test = TestConfig( + name=data.name, + exes=targets, + exfunc=exfunc, + idxsim=0, # TODO: remove parameter from TestConfig + mf6_regression=True, + require_failure=data.xfail, + make_comparison=data.compare) + + test.set_model(sim.simulation_data.mfpath.get_sim_path(), testModel=False) + test.run() + test.compare() diff --git a/autotest/test_gwf_ats01.py b/autotest/test_gwf_ats01.py index be62b72fdea..32394fee25b 100644 --- a/autotest/test_gwf_ats01.py +++ b/autotest/test_gwf_ats01.py @@ -8,30 +8,11 @@ import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) +import flopy -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["gwf_ats01a"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" nlay, nrow, ncol = 1, 1, 2 # set dt0, dtmin, dtmax, dtadj, dtfailadj @@ -198,11 +179,8 @@ def build_model(idx, dir): def eval_flow(sim): print("evaluating flow...") - name = ex[sim.idxsim] - gwfname = name - # This will fail if budget numbers cannot be read - fpth = os.path.join(sim.simpath, f"{gwfname}.lst") + fpth = os.path.join(sim.simpath, f"{sim.name}.lst") mflist = flopy.utils.Mf6ListBudget(fpth) names = mflist.get_record_names() inc = mflist.get_incremental() @@ -212,7 +190,7 @@ def eval_flow(sim): assert v == 10.0, f"Last time should be 10. Found {v}" # ensure obs results changing monotonically - fpth = os.path.join(sim.simpath, gwfname + ".obs.csv") + fpth = os.path.join(sim.simpath, sim.name + ".obs.csv") try: tc = np.genfromtxt(fpth, names=True, delimiter=",") except: @@ -226,39 +204,14 @@ def eval_flow(sim): assert np.all(np.diff(v) < 0), msg v = tc["time"][-1] assert v == 10.0, f"Last time should be 10. Found {v}" - return -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_flow, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_flow, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + workspace = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, workspace) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_flow, idxsim=0), workspace) diff --git a/autotest/test_gwf_ats02.py b/autotest/test_gwf_ats02.py index eea0c7c2fdd..2386d972def 100644 --- a/autotest/test_gwf_ats02.py +++ b/autotest/test_gwf_ats02.py @@ -9,30 +9,11 @@ import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +import flopy + +from harness import TestHarness, TestConfig ex = ["gwf_ats02a"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" nlay, nrow, ncol = 5, 1, 1 botm = [80.0, 60.0, 40.0, 20.0, 0.0] @@ -194,11 +175,9 @@ def build_model(idx, dir): def make_plot(sim): print("making plots...") - name = ex[sim.idxsim] - ws = exdirs[sim.idxsim] - gwfname = name + ws = sim.simpath - fname = gwfname + ".hds" + fname = sim.name + ".hds" fname = os.path.join(ws, fname) hobj = flopy.utils.HeadFile(fname, precision="double") head = hobj.get_alldata()[:, :, 0, 0] @@ -231,14 +210,8 @@ def make_plot(sim): def eval_flow(sim): print("evaluating flow...") - name = ex[sim.idxsim] - gwfname = name - - if False: - make_plot(sim) - # This will fail if budget numbers cannot be read - fpth = os.path.join(sim.simpath, f"{gwfname}.lst") + fpth = os.path.join(sim.simpath, f"{sim.name}.lst") mflist = flopy.utils.Mf6ListBudget(fpth) names = mflist.get_record_names() inc = mflist.get_incremental() @@ -248,7 +221,7 @@ def eval_flow(sim): assert v == 20.0, f"Last time should be 20. Found {v}" # ensure obs results changing monotonically - fpth = os.path.join(sim.simpath, gwfname + ".obs.csv") + fpth = os.path.join(sim.simpath, sim.name + ".obs.csv") try: tc = np.genfromtxt(fpth, names=True, delimiter=",") except: @@ -259,38 +232,11 @@ def eval_flow(sim): ), "layer 1 should be dry for this period" -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_flow, idxsim=idx)) - - return - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_flow, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, 0, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_flow, idxsim=0), str(function_tmpdir)) diff --git a/autotest/test_gwf_ats03.py b/autotest/test_gwf_ats03.py index 8c4ee64715f..37c4ec13f5c 100644 --- a/autotest/test_gwf_ats03.py +++ b/autotest/test_gwf_ats03.py @@ -15,30 +15,12 @@ import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) +import flopy -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["gwf_ats03a"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" nlay, nrow, ncol = 1, 1, 10 @@ -214,11 +196,8 @@ def build_model(idx, dir): def eval_flow(sim): print("evaluating flow...") - name = ex[sim.idxsim] - gwfname = name - # ensure obs2 (a constant head time series) drops linearly from 100 to 50 - fpth = os.path.join(sim.simpath, gwfname + ".obs.csv") + fpth = os.path.join(sim.simpath, sim.name + ".obs.csv") try: tc = np.genfromtxt(fpth, names=True, delimiter=",") except: @@ -230,36 +209,11 @@ def eval_flow(sim): assert np.allclose(answer, result), msg -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_flow, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_flow, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, 0, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_flow, idxsim=0), str(function_tmpdir)) diff --git a/autotest/test_gwf_ats_lak01.py b/autotest/test_gwf_ats_lak01.py index f362b79a298..745ac672882 100644 --- a/autotest/test_gwf_ats_lak01.py +++ b/autotest/test_gwf_ats_lak01.py @@ -3,28 +3,15 @@ # a smaller time step. import os -import sys import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) +import flopy -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["gwf_ats_lak_01a"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) - -# store global gwf for subsequent plotting gwf = None @@ -236,9 +223,6 @@ def build_model(idx, dir): def make_plot_xsect(sim, headall, stageall): print("making plots...") - name = ex[sim.idxsim] - ws = exdirs[sim.idxsim] - import matplotlib.patches as patches import matplotlib.pyplot as plt from matplotlib.collections import PatchCollection @@ -274,18 +258,13 @@ def make_plot_xsect(sim, headall, stageall): # ax.set_ylim(-10, 5) fname = "fig-xsect.pdf" - fname = os.path.join(ws, fname) + fname = os.path.join(sim.simpath, fname) plt.savefig(fname, bbox_inches="tight") - return - def make_plot(sim, times, headall, stageall): print("making plots...") - name = ex[sim.idxsim] - ws = exdirs[sim.idxsim] - import matplotlib.pyplot as plt fig = plt.figure(figsize=(6, 4)) @@ -296,11 +275,9 @@ def make_plot(sim, times, headall, stageall): ax.plot(times, h, "bo-", label="max head") fname = "fig-timeseries.pdf" - fname = os.path.join(ws, fname) + fname = os.path.join(sim.simpath, fname) plt.savefig(fname, bbox_inches="tight") - return - def get_kij_from_node(node, nrow, ncol): "return zero based k, i, j from zero based node number" @@ -316,16 +293,14 @@ def eval_results(sim): print("evaluating results...") # calculate volume of water and make sure it is conserved - name = ex[sim.idxsim] - gwfname = name - fname = gwfname + ".lak.bin" + fname = sim.name + ".lak.bin" fname = os.path.join(sim.simpath, fname) assert os.path.isfile(fname) bobj = flopy.utils.HeadFile(fname, text="STAGE") times = bobj.get_times() stage = bobj.get_alldata() - fname = gwfname + ".cbc" + fname = sim.name + ".cbc" fname = os.path.join(sim.simpath, fname) bobj = flopy.utils.CellBudgetFile(fname, precision="double", verbose=False) times = bobj.get_times() @@ -369,7 +344,7 @@ def eval_results(sim): print(msg) assert all_passed, "found recharge applied to cell beneath active lake" - fname = gwfname + ".hds" + fname = sim.name + ".hds" fname = os.path.join(sim.simpath, fname) assert os.path.isfile(fname) hobj = flopy.utils.HeadFile(fname) @@ -431,43 +406,16 @@ def eval_results(sim): errmsg = "lake stage does not match known answer" assert np.allclose(stage_answer, stage.flatten()), errmsg - if False: - make_plot(sim, times, head, stage) - make_plot_xsect(sim, head, stage) - - return + # make_plot(sim, times, head, stage) + # make_plot_xsect(sim, head, stage) -# - No need to change any code below +@pytest.mark.slow @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_results, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_results, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, 0, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_results, idxsim=0), str(function_tmpdir)) diff --git a/autotest/test_gwf_auxvars.py b/autotest/test_gwf_auxvars.py index 8a7704586a7..6cbaa3370ed 100644 --- a/autotest/test_gwf_auxvars.py +++ b/autotest/test_gwf_auxvars.py @@ -4,29 +4,11 @@ import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +import flopy + +from harness import TestHarness, TestConfig ex = ["aux01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) auxvar1 = 101.0 auxvar2 = 102.0 @@ -317,39 +299,12 @@ def eval_model(sim): assert np.allclose(r["AUX1"], auxvar1) assert np.allclose(r["AUX2"], auxvar2) - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_model, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_model, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_model, idxsim=idx), str(function_tmpdir)) diff --git a/autotest/test_gwf_auxvars02.py b/autotest/test_gwf_auxvars02.py index 80a38bc6fa3..8b82329c47c 100644 --- a/autotest/test_gwf_auxvars02.py +++ b/autotest/test_gwf_auxvars02.py @@ -4,29 +4,11 @@ import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +import flopy + +from harness import TestHarness, TestConfig ex = ["aux02"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) def build_model(idx, dir): @@ -138,39 +120,12 @@ def eval_model(sim): aname = f"AUX{a}" assert np.allclose(r[aname], a) - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_model, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_model, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_model, idxsim=idx), str(function_tmpdir)) diff --git a/autotest/test_gwf_boundname01.py b/autotest/test_gwf_boundname01.py index d53c5852ce5..502dff47b5d 100644 --- a/autotest/test_gwf_boundname01.py +++ b/autotest/test_gwf_boundname01.py @@ -3,32 +3,13 @@ import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +import flopy + +from harness import TestHarness, TestConfig ex = [ "bndname01", ] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" def build_model(idx, exdir): @@ -176,71 +157,25 @@ def replace_quotes(idx, exdir): def eval_obs(sim): - idx = sim.idxsim - ws = exdirs[idx] - name = ex[idx] - print("evaluating observations results..." f"({name})") + print("evaluating observations results..." f"({sim.name})") - fpth = os.path.join(ws, f"gwf_{name}.chd.obs.csv") + fpth = os.path.join(sim.simpath, f"gwf_{sim.name}.chd.obs.csv") obs0 = np.genfromtxt(fpth, delimiter=",", names=True) names0 = obs0.dtype.names - fpth = os.path.join(ws, "mf6", f"gwf_{name}.chd.obs.csv") + fpth = os.path.join(sim.simpath, "mf6", f"gwf_{sim.name}.chd.obs.csv") obs1 = np.genfromtxt(fpth, delimiter=",", names=True) names1 = obs1.dtype.names assert names0 == names1, "observation names are not identical" - assert np.array_equal(obs0, obs1), "observations are not identical" - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, exdir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, exdir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, exdir) - - # replace quotes - replace_quotes(idx, exdir) - - # run the test model - test.run_mf6( - Simulation( - exdir, - idxsim=idx, - ) - ) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build and run the test model - for idx, exdir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, exdir) - sim = Simulation( - exdir, - idxsim=idx, - exfunc=eval_obs, - ) - replace_quotes(idx, exdir) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, 0, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, idxsim=0), str(function_tmpdir)) diff --git a/autotest/test_gwf_buy_lak01.py b/autotest/test_gwf_buy_lak01.py index 0b9a7a8c668..a54fb74a527 100644 --- a/autotest/test_gwf_buy_lak01.py +++ b/autotest/test_gwf_buy_lak01.py @@ -10,28 +10,18 @@ # 3. Buoyancy package with lake and aquifer density = 1024.5 import os -import sys import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) +import flopy -from framework import testing_framework -from simulation import Simulation + +from harness import TestHarness, TestConfig ex = ["buy_lak_01a"] # , 'buy_lak_01b', 'buy_lak_01c'] buy_on_list = [False] # , True, True] concbuylist = [0.0] # , 0., 35.] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) def build_model(idx, dir): @@ -224,8 +214,7 @@ def eval_results(sim): print("evaluating results...") # calculate volume of water and make sure it is conserved - name = ex[sim.idxsim] - gwfname = "gwf_" + name + gwfname = "gwf_" + sim.name fname = gwfname + ".lak.bin" fname = os.path.join(sim.simpath, fname) assert os.path.isfile(fname) @@ -265,36 +254,11 @@ def eval_results(sim): # assert False -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_results, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_results, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, 0, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_results, idxsim=0), str(function_tmpdir)) diff --git a/autotest/test_gwf_buy_lak02.py b/autotest/test_gwf_buy_lak02.py index 86a8a094e64..b95afc86f48 100644 --- a/autotest/test_gwf_buy_lak02.py +++ b/autotest/test_gwf_buy_lak02.py @@ -1,228 +1,83 @@ -# Test the buoyancy package and the variable density flows between the lake -# and the gwf model. This model has 4 layers and a lake incised within it. -# The model is transient and has heads in the aquifer higher than the initial -# stage in the lake. As the model runs, the lake and aquifer equalize and -# should end up at the same level. The test ensures that the initial and -# final water volumes in the entire system are the same. This test is different -# from the previous test in that transport is active. There are four -# different cases: -# 1. lak and aquifer have concentration of 0. -# 2. lak and aquifer have concentration of 35. -# 3. lak has concentration of 0., aquifer is 35. -# 4. lak has concentration of 35., aquifer is 0. - import os -import sys +from typing import NamedTuple +import flopy import numpy as np -import pytest - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation - -ex = ["buy_lak_02a", "buy_lak_02b", "buy_lak_02c", "buy_lak_02d"] -gwt_conc_list = [0.0, 35.0, 35.0, 0.0] -lak_conc_list = [0.0, 35.0, 0.0, 35.0] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) - - -def build_model(idx, dir): - lx = 7.0 - lz = 4.0 - nlay = 4 - nrow = 1 - ncol = 7 - nper = 1 - delc = 1.0 - delr = lx / ncol - delz = lz / nlay - top = 4.0 - botm = [3.0, 2.0, 1.0, 0.0] - - perlen = [50.0] - nstp = [50] - tsmult = [1.0] - - Kh = 1.0 - Kv = 1.0 - - tdis_rc = [] - for i in range(nper): - tdis_rc.append((perlen[i], nstp[i], tsmult[i])) - - nouter, ninner = 700, 300 - hclose, rclose, relax = 1e-8, 1e-6, 0.97 - - name = ex[idx] - - # build MODFLOW 6 files - ws = dir - sim = flopy.mf6.MFSimulation( - sim_name=name, version="mf6", exe_name="mf6", sim_ws=ws - ) - # create tdis package - tdis = flopy.mf6.ModflowTdis( - sim, time_units="DAYS", nper=nper, perioddata=tdis_rc - ) - - # create gwf model - gwfname = "gwf_" + name - gwtname = "gwt_" + name - - gwf = flopy.mf6.ModflowGwf(sim, modelname=gwfname, newtonoptions="NEWTON") - - imsgwf = flopy.mf6.ModflowIms( - sim, - print_option="ALL", - outer_dvclose=hclose, - outer_maximum=nouter, - under_relaxation="NONE", - inner_maximum=ninner, - inner_dvclose=hclose, - rcloserecord=f"{rclose} strict", - linear_acceleration="BICGSTAB", - scaling_method="NONE", - reordering_method="NONE", - relaxation_factor=relax, - filename=f"{gwfname}.ims", - ) - - idomain = np.full((nlay, nrow, ncol), 1) - idomain[0, 0, 1:6] = 0 - idomain[1, 0, 2:5] = 0 - idomain[2, 0, 3:4] = 0 - dis = flopy.mf6.ModflowGwfdis( - gwf, - nlay=nlay, - nrow=nrow, - ncol=ncol, - delr=delr, - delc=delc, - top=top, - botm=botm, - idomain=idomain, - ) - - # initial conditions - strt = np.zeros((nlay, nrow, ncol), dtype=float) - strt[0, 0, :] = 3.5 - strt[1, 0, :] = 3.0 - strt[1, 0, 1:6] = 2.5 - strt[2, 0, :] = 2.0 - strt[3, 0, :] = 1.0 - ic = flopy.mf6.ModflowGwfic(gwf, strt=strt) - - # node property flow - npf = flopy.mf6.ModflowGwfnpf( - gwf, - xt3doptions=False, - save_flows=True, - save_specific_discharge=True, - icelltype=1, - k=Kh, - k33=Kv, - ) - - sto = flopy.mf6.ModflowGwfsto(gwf, sy=0.3, ss=0.0, iconvert=1) - - buy_on = True - if buy_on: - pd = [(0, 0.7, 0.0, gwtname, "CONCENTRATION")] - buy = flopy.mf6.ModflowGwfbuy(gwf, denseref=1000.0, packagedata=pd) - - nlakeconn = 11 # note: number of connections for this lake - # pak_data = [lakeno, strt, nlakeconn, testauxvar, concentration, boundname] - pak_data = [(0, 2.25, nlakeconn, 0.0, 0.0)] - - connlen = delr / 2.0 - connwidth = delc - bedleak = "None" - con_data = [ - # con_data=(lakeno,iconn,(cellid),claktype,bedleak,belev,telev,connlen,connwidth ) - (0, 0, (0, 0, 0), "HORIZONTAL", bedleak, 10, 10, connlen, connwidth), - (0, 1, (1, 0, 1), "VERTICAL", bedleak, 10, 10, connlen, connwidth), - (0, 2, (1, 0, 1), "HORIZONTAL", bedleak, 10, 10, connlen, connwidth), - (0, 3, (2, 0, 2), "VERTICAL", bedleak, 10, 10, connlen, connwidth), - (0, 4, (2, 0, 2), "HORIZONTAL", bedleak, 10, 10, connlen, connwidth), - (0, 5, (3, 0, 3), "VERTICAL", bedleak, 10, 10, connlen, connwidth), - (0, 6, (2, 0, 4), "HORIZONTAL", bedleak, 10, 10, connlen, connwidth), - (0, 7, (2, 0, 4), "VERTICAL", bedleak, 10, 10, connlen, connwidth), - (0, 8, (1, 0, 5), "HORIZONTAL", bedleak, 10, 10, connlen, connwidth), - (0, 9, (1, 0, 5), "VERTICAL", bedleak, 10, 10, connlen, connwidth), - (0, 10, (0, 0, 6), "HORIZONTAL", bedleak, 10, 10, connlen, connwidth), - ] - - # period data - p_data = [ - (0, "STATUS", "ACTIVE"), - ] - - # note: for specifying lake number, use fortran indexing! - fname = f"{gwfname}.lak.obs.csv" - lak_obs = { - fname: [ - ("lakestage", "stage", 1), - ("lakevolume", "volume", 1), - ("lak1", "lak", 1, 1), - ("lak2", "lak", 1, 2), - ("lak3", "lak", 1, 3), - ("lak4", "lak", 1, 4), - ("lak5", "lak", 1, 5), - ("lak6", "lak", 1, 6), - ("lak7", "lak", 1, 7), - ("lak8", "lak", 1, 8), - ("lak9", "lak", 1, 9), - ("lak10", "lak", 1, 10), - ("lak11", "lak", 1, 11), - ], - "digits": 10, - } - - lak = flopy.mf6.modflow.ModflowGwflak( - gwf, - save_flows=True, - print_input=True, - print_flows=True, - print_stage=True, - stage_filerecord=f"{gwfname}.lak.bin", - budget_filerecord=f"{gwfname}.lak.bud", - nlakes=len(pak_data), - ntables=0, - packagedata=pak_data, - pname="LAK-1", - connectiondata=con_data, - perioddata=p_data, - observations=lak_obs, - auxiliary=["TESTAUXVAR", "CONCENTRATION"], - ) - - # output control - oc = flopy.mf6.ModflowGwfoc( - gwf, - budget_filerecord=f"{gwfname}.cbc", - head_filerecord=f"{gwfname}.hds", - headprintrecord=[("COLUMNS", 10, "WIDTH", 15, "DIGITS", 6, "GENERAL")], - saverecord=[("HEAD", "ALL"), ("BUDGET", "ALL")], - printrecord=[("HEAD", "LAST"), ("BUDGET", "LAST")], - ) - - # create gwt model - transport = True - if transport: - - gwt = flopy.mf6.ModflowGwt(sim, modelname=gwtname) - - imsgwt = flopy.mf6.ModflowIms( +from pytest_cases import parametrize, parametrize_with_cases + +from harness import TestConfig + + +class GwfBuyLakCases: + """ + Test the buoyancy package and the variable density flows between the lake + and the gwf model. This model has 4 layers and a lake incised within it. + The model is transient and has heads in the aquifer higher than the initial + stage in the lake. As the model runs, the lake and aquifer equalize and + should end up at the same level. The test ensures that the initial and + final water volumes in the entire system are the same. This test is different + from the previous test in that transport is active. There are four + different cases: + 1. lak and aquifer have concentration of 0. + 2. lak and aquifer have concentration of 35. + 3. lak has concentration of 0., aquifer is 35. + 4. lak has concentration of 35., aquifer is 0. + """ + + class Data(NamedTuple): + name: str + gwt_conc: float + lak_conc: float + + @parametrize(data=[ + Data(name="a", gwt_conc=0, lak_conc=0), + Data(name="b", gwt_conc=35, lak_conc=35), + Data(name="c", gwt_conc=35, lak_conc=0), + Data(name="d", gwt_conc=0, lak_conc=35), + ]) + def case_generator(self, data, tmpdir): + lx = 7.0 + lz = 4.0 + nlay = 4 + nrow = 1 + ncol = 7 + nper = 1 + delc = 1.0 + delr = lx / ncol + delz = lz / nlay + top = 4.0 + botm = [3.0, 2.0, 1.0, 0.0] + + perlen = [50.0] + nstp = [50] + tsmult = [1.0] + + Kh = 1.0 + Kv = 1.0 + + tdis_rc = [] + for i in range(nper): + tdis_rc.append((perlen[i], nstp[i], tsmult[i])) + + nouter, ninner = 700, 300 + hclose, rclose, relax = 1e-8, 1e-6, 0.97 + + # build MODFLOW 6 files + sim = flopy.mf6.MFSimulation( + sim_name=data.name, version="mf6", exe_name="mf6", sim_ws=str(tmpdir) + ) + # create tdis package + tdis = flopy.mf6.ModflowTdis( + sim, time_units="DAYS", nper=nper, perioddata=tdis_rc + ) + + # create gwf model + gwfname = "gwf_" + data.name + gwtname = "gwt_" + data.name + + gwf = flopy.mf6.ModflowGwf(sim, modelname=gwfname, newtonoptions="NEWTON") + + imsgwf = flopy.mf6.ModflowIms( sim, print_option="ALL", outer_dvclose=hclose, @@ -235,12 +90,15 @@ def build_model(idx, dir): scaling_method="NONE", reordering_method="NONE", relaxation_factor=relax, - filename=f"{gwtname}.ims", + filename=f"{gwfname}.ims", ) - sim.register_ims_package(imsgwt, [gwt.name]) - dis = flopy.mf6.ModflowGwtdis( - gwt, + idomain = np.full((nlay, nrow, ncol), 1) + idomain[0, 0, 1:6] = 0 + idomain[1, 0, 2:5] = 0 + idomain[2, 0, 3:4] = 0 + dis = flopy.mf6.ModflowGwfdis( + gwf, nlay=nlay, nrow=nrow, ncol=ncol, @@ -252,181 +110,292 @@ def build_model(idx, dir): ) # initial conditions - strt = gwt_conc_list[idx] - ic = flopy.mf6.ModflowGwtic(gwt, strt=strt) - - # advection - adv = flopy.mf6.ModflowGwtadv(gwt, scheme="UPSTREAM") - - # storage - porosity = 0.30 - sto = flopy.mf6.ModflowGwtmst(gwt, porosity=porosity) + strt = np.zeros((nlay, nrow, ncol), dtype=float) + strt[0, 0, :] = 3.5 + strt[1, 0, :] = 3.0 + strt[1, 0, 1:6] = 2.5 + strt[2, 0, :] = 2.0 + strt[3, 0, :] = 1.0 + ic = flopy.mf6.ModflowGwfic(gwf, strt=strt) + + # node property flow + npf = flopy.mf6.ModflowGwfnpf( + gwf, + xt3doptions=False, + save_flows=True, + save_specific_discharge=True, + icelltype=1, + k=Kh, + k33=Kv, + ) - # sources - sourcerecarray = [ - (), + sto = flopy.mf6.ModflowGwfsto(gwf, sy=0.3, ss=0.0, iconvert=1) + + buy_on = True + if buy_on: + pd = [(0, 0.7, 0.0, gwtname, "CONCENTRATION")] + buy = flopy.mf6.ModflowGwfbuy(gwf, denseref=1000.0, packagedata=pd) + + nlakeconn = 11 # note: number of connections for this lake + # pak_data = [lakeno, strt, nlakeconn, testauxvar, concentration, boundname] + pak_data = [(0, 2.25, nlakeconn, 0.0, 0.0)] + + connlen = delr / 2.0 + connwidth = delc + bedleak = "None" + con_data = [ + # con_data=(lakeno,iconn,(cellid),claktype,bedleak,belev,telev,connlen,connwidth ) + (0, 0, (0, 0, 0), "HORIZONTAL", bedleak, 10, 10, connlen, connwidth), + (0, 1, (1, 0, 1), "VERTICAL", bedleak, 10, 10, connlen, connwidth), + (0, 2, (1, 0, 1), "HORIZONTAL", bedleak, 10, 10, connlen, connwidth), + (0, 3, (2, 0, 2), "VERTICAL", bedleak, 10, 10, connlen, connwidth), + (0, 4, (2, 0, 2), "HORIZONTAL", bedleak, 10, 10, connlen, connwidth), + (0, 5, (3, 0, 3), "VERTICAL", bedleak, 10, 10, connlen, connwidth), + (0, 6, (2, 0, 4), "HORIZONTAL", bedleak, 10, 10, connlen, connwidth), + (0, 7, (2, 0, 4), "VERTICAL", bedleak, 10, 10, connlen, connwidth), + (0, 8, (1, 0, 5), "HORIZONTAL", bedleak, 10, 10, connlen, connwidth), + (0, 9, (1, 0, 5), "VERTICAL", bedleak, 10, 10, connlen, connwidth), + (0, 10, (0, 0, 6), "HORIZONTAL", bedleak, 10, 10, connlen, connwidth), ] - ssm = flopy.mf6.ModflowGwtssm(gwt, sources=sourcerecarray) - lak_conc = lak_conc_list[idx] - lktpackagedata = [ - (0, lak_conc, 99.0, 999.0, "mylake"), + # period data + p_data = [ + (0, "STATUS", "ACTIVE"), ] - lkt = flopy.mf6.modflow.ModflowGwtlkt( - gwt, - boundnames=True, + + # note: for specifying lake number, use fortran indexing! + fname = f"{gwfname}.lak.obs.csv" + lak_obs = { + fname: [ + ("lakestage", "stage", 1), + ("lakevolume", "volume", 1), + ("lak1", "lak", 1, 1), + ("lak2", "lak", 1, 2), + ("lak3", "lak", 1, 3), + ("lak4", "lak", 1, 4), + ("lak5", "lak", 1, 5), + ("lak6", "lak", 1, 6), + ("lak7", "lak", 1, 7), + ("lak8", "lak", 1, 8), + ("lak9", "lak", 1, 9), + ("lak10", "lak", 1, 10), + ("lak11", "lak", 1, 11), + ], + "digits": 10, + } + + lak = flopy.mf6.modflow.ModflowGwflak( + gwf, save_flows=True, print_input=True, print_flows=True, - print_concentration=True, - concentration_filerecord=gwtname + ".lkt.bin", - budget_filerecord="gwtlak1.bud", - packagedata=lktpackagedata, - pname="LKT-1", - flow_package_name="LAK-1", - flow_package_auxiliary_name="CONCENTRATION", - auxiliary=["aux1", "aux2"], + print_stage=True, + stage_filerecord=f"{gwfname}.lak.bin", + budget_filerecord=f"{gwfname}.lak.bud", + nlakes=len(pak_data), + ntables=0, + packagedata=pak_data, + pname="LAK-1", + connectiondata=con_data, + perioddata=p_data, + observations=lak_obs, + auxiliary=["TESTAUXVAR", "CONCENTRATION"], ) - # output control - oc = flopy.mf6.ModflowGwtoc( - gwt, - budget_filerecord=f"{gwtname}.cbc", - concentration_filerecord=f"{gwtname}.ucn", - concentrationprintrecord=[ - ("COLUMNS", 10, "WIDTH", 15, "DIGITS", 6, "GENERAL") - ], - saverecord=[("CONCENTRATION", "ALL")], - printrecord=[("CONCENTRATION", "ALL"), ("BUDGET", "ALL")], - ) - - fmi = flopy.mf6.ModflowGwtfmi(gwt, flow_imbalance_correction=True) - # GWF GWT exchange - gwfgwt = flopy.mf6.ModflowGwfgwt( - sim, - exgtype="GWF6-GWT6", - exgmnamea=gwfname, - exgmnameb=gwtname, - filename=f"{name}.gwfgwt", + # output control + oc = flopy.mf6.ModflowGwfoc( + gwf, + budget_filerecord=f"{gwfname}.cbc", + head_filerecord=f"{gwfname}.hds", + headprintrecord=[("COLUMNS", 10, "WIDTH", 15, "DIGITS", 6, "GENERAL")], + saverecord=[("HEAD", "ALL"), ("BUDGET", "ALL")], + printrecord=[("HEAD", "LAST"), ("BUDGET", "LAST")], ) - return sim, None - - -def eval_results(sim): - print("evaluating results...") - - # calculate volume of water and make sure it is conserved - name = ex[sim.idxsim] - gwfname = "gwf_" + name - gwtname = "gwt_" + name - fname = gwfname + ".lak.bin" - fname = os.path.join(sim.simpath, fname) - assert os.path.isfile(fname) - bobj = flopy.utils.HeadFile(fname, text="STAGE") - stage = bobj.get_alldata().flatten() - # print(stage) - - fname = gwfname + ".hds" - fname = os.path.join(sim.simpath, fname) - assert os.path.isfile(fname) - hobj = flopy.utils.HeadFile(fname) - head = hobj.get_data() - # print(head) - - fname = gwtname + ".ucn" - fname = os.path.join(sim.simpath, fname) - assert os.path.isfile(fname) - cobj = flopy.utils.HeadFile(fname, text="CONCENTRATION") - conc = cobj.get_data() - - fname = gwtname + ".lkt.bin" - fname = os.path.join(sim.simpath, fname) - assert os.path.isfile(fname) - cobj = flopy.utils.HeadFile(fname, text="CONCENTRATION") - clak = cobj.get_data().flatten() - - # calculate initial water volume - v0 = 3.5 * 2 # outermost columns - v0 += 2.5 * 2 # next innermost columns - v0 += 2.0 * 2 # next innermost columns - v0 += 1.0 * 1 # middle column - v0 = v0 * 0.3 # specific yield - - m0 = v0 * gwt_conc_list[sim.idxsim] - vl0 = (2.25 - 2.0) * 2 + (2.25 - 1.0) - m0 += vl0 * lak_conc_list[sim.idxsim] - v0 += vl0 - print(f"initial volume of water in model = {v0}") - print(f"initial mass of solute in model = {m0}") - - # calculate ending water volume in model - head = np.where(head > 1e10, -1e10, head) - botm = [3, 2, 1, 0] - top = [4, 3, 2, 1] - nlay, nrow, ncol = head.shape - v = 0 - m = 0.0 - for k in range(nlay): - for i in range(nrow): - for j in range(ncol): - h = min(head[k, i, j], top[k]) - dz = h - botm[k] - vcell = max(dz, 0.0) * 0.3 - v += vcell - m += vcell * conc[k, i, j] - - s = stage[-1] - vl = (s - 2.0) * 2 + (s - 1.0) - v = v + vl - m += vl * clak[0] - print(f"final volume of water in model = {v}") - print(f"final mass of solute in model = {m}") - - # check to make sure starting water volume same as equalized final volume - errmsg = f"initial and final water volume not equal: {v0} {v}" - assert np.allclose(v0, v), errmsg - - # check to make sure starting starting solute mass same as equalized solute mass - errmsg = f"initial and final solute mass not equal: {m0} {m}" - assert np.allclose(m0, m), errmsg - - # todo: add a better check of the lake concentrations - # assert False - - return - - -# - No need to change any code below -@pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), -) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_results, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_results, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() + # create gwt model + transport = True + if transport: + gwt = flopy.mf6.ModflowGwt(sim, modelname=gwtname) + + imsgwt = flopy.mf6.ModflowIms( + sim, + print_option="ALL", + outer_dvclose=hclose, + outer_maximum=nouter, + under_relaxation="NONE", + inner_maximum=ninner, + inner_dvclose=hclose, + rcloserecord=f"{rclose} strict", + linear_acceleration="BICGSTAB", + scaling_method="NONE", + reordering_method="NONE", + relaxation_factor=relax, + filename=f"{gwtname}.ims", + ) + sim.register_ims_package(imsgwt, [gwt.name]) + + dis = flopy.mf6.ModflowGwtdis( + gwt, + nlay=nlay, + nrow=nrow, + ncol=ncol, + delr=delr, + delc=delc, + top=top, + botm=botm, + idomain=idomain, + ) + + # initial conditions + strt = data.gwt_conc + ic = flopy.mf6.ModflowGwtic(gwt, strt=strt) + + # advection + adv = flopy.mf6.ModflowGwtadv(gwt, scheme="UPSTREAM") + + # storage + porosity = 0.30 + sto = flopy.mf6.ModflowGwtmst(gwt, porosity=porosity) + + # sources + sourcerecarray = [ + (), + ] + ssm = flopy.mf6.ModflowGwtssm(gwt, sources=sourcerecarray) + + lak_conc = data.lak_conc + lktpackagedata = [ + (0, lak_conc, 99.0, 999.0, "mylake"), + ] + lkt = flopy.mf6.modflow.ModflowGwtlkt( + gwt, + boundnames=True, + save_flows=True, + print_input=True, + print_flows=True, + print_concentration=True, + concentration_filerecord=gwtname + ".lkt.bin", + budget_filerecord="gwtlak1.bud", + packagedata=lktpackagedata, + pname="LKT-1", + flow_package_name="LAK-1", + flow_package_auxiliary_name="CONCENTRATION", + auxiliary=["aux1", "aux2"], + ) + # output control + oc = flopy.mf6.ModflowGwtoc( + gwt, + budget_filerecord=f"{gwtname}.cbc", + concentration_filerecord=f"{gwtname}.ucn", + concentrationprintrecord=[ + ("COLUMNS", 10, "WIDTH", 15, "DIGITS", 6, "GENERAL") + ], + saverecord=[("CONCENTRATION", "ALL")], + printrecord=[("CONCENTRATION", "ALL"), ("BUDGET", "ALL")], + ) + + fmi = flopy.mf6.ModflowGwtfmi(gwt, flow_imbalance_correction=True) + + # GWF GWT exchange + gwfgwt = flopy.mf6.ModflowGwfgwt( + sim, + exgtype="GWF6-GWT6", + exgmnamea=gwfname, + exgmnameb=gwtname, + filename=f"{data.name}.gwfgwt", + ) + + return data, sim, None, self.eval_results + + def eval_results(self, sim, data): + print("evaluating results...") + + # calculate volume of water and make sure it is conserved + gwfname = "gwf_" + data.name + gwtname = "gwt_" + data.name + fname = gwfname + ".lak.bin" + fname = os.path.join(sim.simpath, fname) + assert os.path.isfile(fname) + bobj = flopy.utils.HeadFile(fname, text="STAGE") + stage = bobj.get_alldata().flatten() + # print(stage) + + fname = gwfname + ".hds" + fname = os.path.join(sim.simpath, fname) + assert os.path.isfile(fname) + hobj = flopy.utils.HeadFile(fname) + head = hobj.get_data() + # print(head) + + fname = gwtname + ".ucn" + fname = os.path.join(sim.simpath, fname) + assert os.path.isfile(fname) + cobj = flopy.utils.HeadFile(fname, text="CONCENTRATION") + conc = cobj.get_data() + + fname = gwtname + ".lkt.bin" + fname = os.path.join(sim.simpath, fname) + assert os.path.isfile(fname) + cobj = flopy.utils.HeadFile(fname, text="CONCENTRATION") + clak = cobj.get_data().flatten() + + # calculate initial water volume + v0 = 3.5 * 2 # outermost columns + v0 += 2.5 * 2 # next innermost columns + v0 += 2.0 * 2 # next innermost columns + v0 += 1.0 * 1 # middle column + v0 = v0 * 0.3 # specific yield + + m0 = v0 * data.gwt_conc + vl0 = (2.25 - 2.0) * 2 + (2.25 - 1.0) + m0 += vl0 * data.lak_conc + v0 += vl0 + print(f"initial volume of water in model = {v0}") + print(f"initial mass of solute in model = {m0}") + + # calculate ending water volume in model + head = np.where(head > 1e10, -1e10, head) + botm = [3, 2, 1, 0] + top = [4, 3, 2, 1] + nlay, nrow, ncol = head.shape + v = 0 + m = 0.0 + for k in range(nlay): + for i in range(nrow): + for j in range(ncol): + h = min(head[k, i, j], top[k]) + dz = h - botm[k] + vcell = max(dz, 0.0) * 0.3 + v += vcell + m += vcell * conc[k, i, j] + + s = stage[-1] + vl = (s - 2.0) * 2 + (s - 1.0) + v = v + vl + m += vl * clak[0] + print(f"final volume of water in model = {v}") + print(f"final mass of solute in model = {m}") + + # check to make sure starting water volume same as equalized final volume + errmsg = f"initial and final water volume not equal: {v0} {v}" + assert np.allclose(v0, v), errmsg + + # check to make sure starting starting solute mass same as equalized solute mass + errmsg = f"initial and final solute mass not equal: {m0} {m}" + assert np.allclose(m0, m), errmsg + + # todo: add a better check of the lake concentrations + + +@parametrize_with_cases("case", cases=[ + GwfBuyLakCases, +]) +def test_mf6model(case, targets): + data, sim, cmp, evl = case + sim.write_simulation() + if cmp: cmp.write_simulation() + simulation = TestConfig(name=data.name, exes=targets, exfunc=evl, idxsim=0) + simulation.set_model(sim.simulation_data.mfpath.get_sim_path(), testModel=False) + simulation.run() + simulation.compare() + evl(simulation, data) diff --git a/autotest/test_gwf_buy_maw01.py b/autotest/test_gwf_buy_maw01.py index 72887e337d7..ff930482834 100644 --- a/autotest/test_gwf_buy_maw01.py +++ b/autotest/test_gwf_buy_maw01.py @@ -15,23 +15,13 @@ import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) +import flopy -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["buy_maw_01a"] # , 'buy_maw_01b', 'buy_maw_01c'] buy_on_list = [False] # , True, True] concbuylist = [0.0] # , 0., 35.] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) def build_model(idx, dir): @@ -200,8 +190,7 @@ def eval_results(sim): print("evaluating results...") # calculate volume of water and make sure it is conserved - name = ex[sim.idxsim] - gwfname = "gwf_" + name + gwfname = "gwf_" + sim.name fname = gwfname + ".maw.bin" fname = os.path.join(sim.simpath, fname) assert os.path.isfile(fname) @@ -262,39 +251,12 @@ def eval_results(sim): print(msg) assert np.allclose(qmaw, -qgwf), msg - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_results, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_results, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, 0, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_results, idxsim=0), str(function_tmpdir)) diff --git a/autotest/test_gwf_buy_sfr01.py b/autotest/test_gwf_buy_sfr01.py index 73749476ff3..41d5e95b7ad 100644 --- a/autotest/test_gwf_buy_sfr01.py +++ b/autotest/test_gwf_buy_sfr01.py @@ -7,21 +7,11 @@ import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) +import flopy -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["buy_sfr_01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) def build_model(idx, dir): @@ -387,9 +377,8 @@ def eval_results(sim): print("evaluating results...") # assign names - name = ex[sim.idxsim] - gwtname = "gwt_" + name - gwfname = "gwf_" + name + gwtname = "gwt_" + sim.name + gwfname = "gwf_" + sim.name # load the sft concentrations and make sure all values are correct fname = gwtname + ".sft.bin" @@ -468,42 +457,9 @@ def eval_results(sim): qcalc, qsim ), f"reach {n} flow {qcalc} not equal {qsim}" - # uncomment when testing - # assert False - - return - - -# - No need to change any code below -@pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), -) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_results, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_results, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - # run main routine - main() +@pytest.mark.parametrize("name", ex) +def test_mf6model(name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, 0, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_results, idxsim=0), str(function_tmpdir)) diff --git a/autotest/test_gwf_chd01.py b/autotest/test_gwf_chd01.py index 8f3bbf79a40..63548280616 100644 --- a/autotest/test_gwf_chd01.py +++ b/autotest/test_gwf_chd01.py @@ -1,35 +1,15 @@ import os -import sys import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +import flopy + +from harness import TestHarness, TestConfig ex = [ "chd01", ] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" def build_model(idx, dir): @@ -142,15 +122,11 @@ def build_model(idx, dir): def eval_model(sim): print("evaluating model...") - name = ex[sim.idxsim] - gwfname = "gwf_" + name + gwfname = "gwf_" + sim.name fpth = os.path.join(sim.simpath, f"{gwfname}.hds") - try: - hobj = flopy.utils.HeadFile(fpth, precision="double") - head = hobj.get_data().flatten() - except: - assert False, f'could not load data from "{fpth}"' + hobj = flopy.utils.HeadFile(fpth, precision="double") + head = hobj.get_data().flatten() # This is the answer to this problem. hres = np.linspace(1, 0, 100) @@ -158,42 +134,9 @@ def eval_model(sim): hres, head ), "simulated head do not match with known solution." - # comment when done testing - # assert False - - return - - -# - No need to change any code below -@pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), -) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_model, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_model, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - # run main routine - main() +@pytest.mark.parametrize("name", ex) +def test_mf6model(name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, 0, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_model, idxsim=0), str(function_tmpdir)) diff --git a/autotest/test_gwf_csub_db01_nr.py b/autotest/test_gwf_csub_db01_nr.py index 1e19d128f54..69dfa15f825 100644 --- a/autotest/test_gwf_csub_db01_nr.py +++ b/autotest/test_gwf_csub_db01_nr.py @@ -1,26 +1,10 @@ import os +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import running_on_CI, testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ( "csub_db01a", @@ -30,9 +14,7 @@ "csub_db01e", "csub_db01f", ) -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) + newtons = ( True, True, @@ -65,16 +47,9 @@ False, False, ) - -ddir = "data" - -# set replace_exe to None to use default executable -replace_exe = None - htol = None dtol = 1e-3 budtol = 0.01 - bud_lst = ( "CSUB-CGELASTIC_IN", "CSUB-CGELASTIC_OUT", @@ -432,51 +407,16 @@ def eval_comp(sim): print(" " + msg) -# - No need to change any code below - - @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # determine if running on CI infrastructure - is_CI = running_on_CI() - r_exe = None - if not is_CI: - if replace_exe is not None: - r_exe = replace_exe - - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6( - Simulation( - dir, exfunc=eval_comp, exe_dict=r_exe, htol=htol, idxsim=idx - ) +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run( + TestConfig( + name=name, exes=targets, exfunc=eval_comp, htol=htol, idxsim=idx + ), + str(function_tmpdir) ) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation( - dir, exfunc=eval_comp, exe_dict=replace_exe, htol=htol, idxsim=idx - ) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_csub_dbgeo01.py b/autotest/test_gwf_csub_dbgeo01.py index c0e0dd9678b..d436151fda1 100644 --- a/autotest/test_gwf_csub_dbgeo01.py +++ b/autotest/test_gwf_csub_dbgeo01.py @@ -3,23 +3,11 @@ import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) +import flopy -from framework import running_on_CI, testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["csub_dbgeo01a"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" - ndcell = [19] strt = [0.0] chdh = [0] @@ -27,15 +15,6 @@ bso = [True] # sstate = [None, True] -# run all examples on Travis -# continuous_integration = [True for idx in range(len(exdirs))] -# the delay bed problems only run on the development version of MODFLOW-2005 -# set travis to True when version 1.13.0 is released -continuous_integration = [True for idx in range(len(exdirs))] - -# set replace_exe to None to use default executable -replace_exe = None - # comparison data compdataa = [ 0.6829965295, @@ -345,7 +324,7 @@ def eval_sub(sim): assert False, f'could not load data from "{fpth}"' # set comparison data - tc0 = compdata[sim.idxsim] + tc0 = compdata[0] # calculate maximum absolute error diff = tc["TCOMP"] - tc0[:] @@ -379,53 +358,13 @@ def eval_sub(sim): sim.success = True print(" " + msg) - return - - -# - No need to change any code below - - -@pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), -) -def test_mf6model(idx, dir): - # determine if running on CI infrastructure - is_CI = running_on_CI() - r_exe = None - if not is_CI: - if replace_exe is not None: - r_exe = replace_exe - - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - if is_CI and not continuous_integration[idx]: - return - test.run_mf6(Simulation(dir, exfunc=eval_sub, exe_dict=r_exe, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation( - dir, exfunc=eval_sub, exe_dict=replace_exe, idxsim=idx - ) - test.run_mf6(sim) - - -# use python testmf6_csub_sub01.py --mf2005 mf2005devdbl -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - # run main routine - main() +@pytest.mark.parametrize("name", ex) +def test_mf6model(name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, 0, str(function_tmpdir)) + test.run(TestConfig( + name=name, + exes=targets, + exfunc=eval_sub, + idxsim=0), str(function_tmpdir)) diff --git a/autotest/test_gwf_csub_inelastic.py b/autotest/test_gwf_csub_inelastic.py index c83b33fae4a..37fff1922aa 100644 --- a/autotest/test_gwf_csub_inelastic.py +++ b/autotest/test_gwf_csub_inelastic.py @@ -1,42 +1,14 @@ import os +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import running_on_CI, testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig paktest = "csub" budtol = 1e-2 - ex = ["csub_de01a"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" - -updatemat = [None, True] -# run all examples on Travis -continuous_integration = [True for idx in range(len(exdirs))] - -# set replace_exe to None to use default executable -replace_exe = None # static model data # spatial discretization @@ -280,50 +252,17 @@ def eval_void(sim): sim.success = True print(" " + msg) - return - -# - No need to change any code below +@pytest.mark.slow @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # determine if running on CI infrastructure - is_CI = running_on_CI() - r_exe = None - if not is_CI: - if replace_exe is not None: - r_exe = replace_exe - - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - if is_CI and not continuous_integration[idx]: - return - - test.run_mf6(Simulation(dir, exfunc=eval_void, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_void, idxsim=idx) - test.run_mf6(sim) - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run(TestConfig( + name=name, + exes=targets, + exfunc=eval_void, + idxsim=idx), str(function_tmpdir)) diff --git a/autotest/test_gwf_csub_ndb01_nr.py b/autotest/test_gwf_csub_ndb01_nr.py index 9155a1d0260..4801ec33892 100644 --- a/autotest/test_gwf_csub_ndb01_nr.py +++ b/autotest/test_gwf_csub_ndb01_nr.py @@ -3,24 +3,10 @@ import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import running_on_CI, testing_framework -from simulation import Simulation +import flopy +from conftest import is_in_ci + +from harness import TestHarness, TestConfig ex = ( "csub_ndb01a", @@ -32,9 +18,6 @@ "csub_ndb01g", "csub_ndb01h", ) -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) newtons = ( True, False, @@ -65,12 +48,6 @@ False, False, ) - -ddir = "data" - -# set replace_exe to None to use default executable -replace_exe = None - htol = None dtol = 1e-3 budtol = 0.01 @@ -403,54 +380,21 @@ def eval_comp(sim): sim.success = True print(" " + msg) - return - - -# - No need to change any code below - @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # determine if running on CI infrastructure - is_CI = running_on_CI() - r_exe = None - if not is_CI: - if replace_exe is not None: - r_exe = replace_exe - - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6( - Simulation( - dir, exfunc=eval_comp, exe_dict=r_exe, htol=htol, idxsim=idx - ) +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run( + TestConfig( + name=name, + exes=targets, + exfunc=eval_comp, + htol=htol, + idxsim=idx + ), + str(function_tmpdir) ) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation( - dir, exfunc=eval_comp, exe_dict=replace_exe, htol=htol, idxsim=idx - ) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_csub_sk01.py b/autotest/test_gwf_csub_sk01.py index 168e941d93b..5a8399a6961 100644 --- a/autotest/test_gwf_csub_sk01.py +++ b/autotest/test_gwf_csub_sk01.py @@ -1,537 +1,453 @@ import os +from typing import NamedTuple, List +import flopy import numpy as np -import pytest - -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import running_on_CI, testing_framework -from simulation import Simulation - -ex = ["csub_sk01a", "csub_sk01b", "csub_sk01c"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -cvopt = [None, None, None] -constantcv = [True, True, True] -ndelaybeds = [0, 0, 0] - -cmppths = ["mf6-regression", "mf6-regression", "mf6-regression"] -tops = [0.0, 0.0, 150.0] -newtons = [False, True, True] - -ddir = "data" - -## run all examples on Travis -# continuous_integration = [False for idx in range(len(exdirs))] -continuous_integration = [True, True, True] - -# set replace_exe to None to use default executable -replace_exe = None - -htol = [None, None, 0.3] -dtol = 1e-3 -budtol = 0.01 - -bud_lst = [ - "CSUB-CGELASTIC_IN", - "CSUB-CGELASTIC_OUT", - "CSUB-WATERCOMP_IN", - "CSUB-WATERCOMP_OUT", -] - -# static model data -nlay, nrow, ncol = 3, 10, 10 -nper = 31 -perlen = [1.0] + [365.2500000 for i in range(nper - 1)] -nstp = [1] + [6 for i in range(nper - 1)] -tsmult = [1.0] + [1.3 for i in range(nper - 1)] -steady = [True] + [False for i in range(nper - 1)] -delr, delc = 1000.0, 2000.0 -top = 0.0 -botm = [-100, -150.0, -350.0] -zthick = [top - botm[0], botm[0] - botm[1], botm[1] - botm[2]] -strt = 100.0 -hnoflo = 1e30 -hdry = -1e30 - -# calculate hk -hk1fact = 1.0 / zthick[1] -hk1 = np.ones((nrow, ncol), dtype=float) * 0.5 * hk1fact -hk1[0, :] = 1000.0 * hk1fact -hk1[-1, :] = 1000.0 * hk1fact -hk1[:, 0] = 1000.0 * hk1fact -hk1[:, -1] = 1000.0 * hk1fact -hk = [20.0, hk1, 5.0] - -# calculate vka -vka = [1e6, 7.5e-5, 1e6] - -# set rest of npf variables -laytyp = [1, 0, 0] -laytypu = [4, 0, 0] -sy = 0.0 # [0.1, 0., 0.] - -nouter, ninner = 500, 300 -hclose, rclose, relax = 1e-9, 1e-6, 1.0 - -tdis_rc = [] -for idx in range(nper): - tdis_rc.append((perlen[idx], nstp[idx], tsmult[idx])) - -# all cells are active -ib = 1 - -# chd data -c = [] -c6 = [] -ccol = [3, 4, 5, 6] -for j in ccol: - c.append([0, nrow - 1, j, strt, strt]) - c6.append([(0, nrow - 1, j), strt]) -cd = {0: c} -cd6 = {0: c6} -maxchd = len(cd[0]) - -# pumping well data -wr = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3] -wc = [0, 1, 8, 9, 0, 9, 0, 9, 0, 0] -wrp = [2, 2, 3, 3] -wcp = [5, 6, 5, 6] -wq = [-14000.0, -8000.0, -5000.0, -3000.0] -d = [] -d6 = [] -for r, c, q in zip(wrp, wcp, wq): - d.append([2, r, c, q]) - d6.append([(2, r, c), q]) -wd = {1: d} -wd6 = {1: d6} -maxwel = len(wd[1]) - -# recharge data -q = 3000.0 / (delr * delc) -v = np.zeros((nrow, ncol), dtype=float) -for r, c in zip(wr, wc): - v[r, c] = q -rech = {0: v} - -# static ibc and sub data -sgm = 0.0 -sgs = 0.0 -omega = 1.0 -void = 0.82 -theta = void / (1.0 + void) -sw = 4.65120000e-10 * 9806.65000000 * theta - -# no delay bed data -nndb = 3 -lnd = [0, 1, 2] -hc = [botm[-1] for k in range(nlay)] -thicknd0 = [zthick[0], zthick[1], zthick[2]] -ccnd0 = [6e-6, 3e-6, 6e-6] -crnd0 = [6e-6, 3e-6, 6e-6] -sfv = [] -sfe = [] -for k in range(nlay): - sfv.append(ccnd0[k] * thicknd0[k]) - sfe.append(crnd0[k] * thicknd0[k]) - -# sub output data -ds15 = [0, 0, 0, 2052, 0, 0, 0, 0, 0, 0, 0, 0] -ds16 = [0, nper - 1, 0, nstp[-1] - 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1] - -# Build MODFLOW 6 files -def get_model(idx, ws): - name = ex[idx] - newton = newtons[idx] - newtonoptions = None - imsla = "CG" - if newton: - newtonoptions = "NEWTON" - imsla = "BICGSTAB" - - # build MODFLOW 6 files - sim = flopy.mf6.MFSimulation( - sim_name=name, version="mf6", exe_name="mf6", sim_ws=ws - ) - # create tdis package - tdis = flopy.mf6.ModflowTdis( - sim, time_units="DAYS", nper=nper, perioddata=tdis_rc - ) - - # create iterative model solution - ims = flopy.mf6.ModflowIms( - sim, - print_option="SUMMARY", - outer_dvclose=hclose, - outer_maximum=nouter, - under_relaxation="NONE", - inner_maximum=ninner, - inner_dvclose=hclose, - rcloserecord=rclose, - linear_acceleration=imsla, - scaling_method="NONE", - reordering_method="NONE", - relaxation_factor=relax, - ) - - # create gwf model - gwf = flopy.mf6.ModflowGwf( - sim, modelname=name, newtonoptions=newtonoptions - ) - - dis = flopy.mf6.ModflowGwfdis( - gwf, - nlay=nlay, - nrow=nrow, - ncol=ncol, - delr=delr, - delc=delc, - top=tops[idx], - botm=botm, - filename=f"{name}.dis", - ) - - # initial conditions - ic = flopy.mf6.ModflowGwfic(gwf, strt=strt, filename=f"{name}.ic") - - # node property flow - npf = flopy.mf6.ModflowGwfnpf( - gwf, - save_flows=False, - # dev_modflowusg_upstream_weighted_saturation=True, - icelltype=laytyp, - cvoptions=cvopt[idx], - k=hk, - k33=vka, - ) - # storage - sto = flopy.mf6.ModflowGwfsto( - gwf, - save_flows=False, - iconvert=laytyp, - ss=0.0, - sy=sy, - storagecoefficient=True, - steady_state={0: True}, - transient={1: True}, - ) - - # recharge - rch = flopy.mf6.ModflowGwfrcha(gwf, readasarrays=True, recharge=rech) - - # wel file - wel = flopy.mf6.ModflowGwfwel( - gwf, - print_input=True, - print_flows=True, - maxbound=maxwel, - stress_period_data=wd6, - save_flows=False, - ) - - # chd files - chd = flopy.mf6.modflow.mfgwfchd.ModflowGwfchd( - gwf, maxbound=maxchd, stress_period_data=cd6, save_flows=False - ) - # csub files - opth = f"{name}.csub.obs" - csub = flopy.mf6.ModflowGwfcsub( - gwf, - head_based=True, - save_flows=True, - ninterbeds=0, - cg_theta=theta, - cg_ske_cr=crnd0, - packagedata=None, - ) - obspos = [(0, 4, 4), (1, 4, 4), (2, 4, 4)] - obstype = ["compaction-cell", "csub-cell"] - obstag = ["tcomp", "csub"] - obsarr = [] - for iobs, cobs in enumerate(obstype): - for jobs, otup in enumerate(obspos): - otag = f"{obstag[iobs]}{jobs + 1}" - obsarr.append((otag, cobs, otup)) - - obsarr2 = [] - obstype2 = [ - "csub", - "inelastic-csub", - "elastic-csub", - "sk", - "ske", - "thickness", - "theta", - "interbed-compaction", - "inelastic-compaction", - "elastic-compaction", - "delay-flowtop", - "delay-flowbot", - ] - iobs = 0 - for cobs in obstype2: - iobs += 1 - otag = f"obs{iobs:03d}" - obsarr2.append((otag, cobs, (0,))) - - obstype3 = [ - "delay-preconstress", - "delay-head", - "delay-gstress", - "delay-estress", - "delay-compaction", - "delay-thickness", - "delay-theta", - ] - for cobs in obstype3: - iobs += 1 - otag = f"obs{iobs:03d}" - obsarr2.append((otag, cobs, (0,), (0,))) - - obsarr3 = [] - obstype4 = [ - "gstress-cell", - "estress-cell", - "thickness-cell", - "coarse-csub", - "wcomp-csub-cell", - "coarse-compaction", - "coarse-theta", - "coarse-thickness", - "csub-cell", - "ske-cell", - "sk-cell", - "theta-cell", - "compaction-cell", +from pytest_cases import parametrize_with_cases, parametrize + +from harness import TestConfig + + +class GwfCsubSkCases: + dtol: float = 1e-3 + budtol: float = 0.01 + bud_lst: List[str] = [ + "CSUB-CGELASTIC_IN", + "CSUB-CGELASTIC_OUT", + "CSUB-WATERCOMP_IN", + "CSUB-WATERCOMP_OUT", ] - for cobs in obstype4: - iobs += 1 - otag = f"obs{iobs:03d}" - obsarr3.append((otag, cobs, obspos[-1])) - orecarray = {} - orecarray["csub_obs.csv"] = obsarr - orecarray["interbed_obs.csv"] = obsarr2 - orecarray["coarse_cell_obs.csv"] = obsarr3 + class Data(NamedTuple): + name: str + cvopt: str + constantcv: bool + ndelaybeds: int + top: float + newton: bool + htol: float + + @parametrize(data=[ + Data('a', None, True, 0, 0, False, None), + Data('b', None, True, 0, 0, True, None), + Data('c', None, True, 0, 15, True, 0.3), + ]) + def case_generator(self, tmpdir, data): + sim = self.get_model(data, tmpdir) + cmp = self.get_model(data, tmpdir / "mf6_regression") + return data, sim, cmp, self.eval_case + + def get_model(self, data, tmpdir): + name = data.name + newton = data.newton + newtonoptions = None + imsla = "CG" + if newton: + newtonoptions = "NEWTON" + imsla = "BICGSTAB" + + # static model data + nlay, nrow, ncol = 3, 10, 10 + nper = 31 + perlen = [1.0] + [365.2500000 for i in range(nper - 1)] + nstp = [1] + [6 for i in range(nper - 1)] + tsmult = [1.0] + [1.3 for i in range(nper - 1)] + steady = [True] + [False for i in range(nper - 1)] + delr, delc = 1000.0, 2000.0 + top = 0.0 + botm = [-100, -150.0, -350.0] + zthick = [top - botm[0], botm[0] - botm[1], botm[1] - botm[2]] + strt = 100.0 + hnoflo = 1e30 + hdry = -1e30 + + # calculate hk + hk1fact = 1.0 / zthick[1] + hk1 = np.ones((nrow, ncol), dtype=float) * 0.5 * hk1fact + hk1[0, :] = 1000.0 * hk1fact + hk1[-1, :] = 1000.0 * hk1fact + hk1[:, 0] = 1000.0 * hk1fact + hk1[:, -1] = 1000.0 * hk1fact + hk = [20.0, hk1, 5.0] + + # calculate vka + vka = [1e6, 7.5e-5, 1e6] + + # set rest of npf variables + laytyp = [1, 0, 0] + laytypu = [4, 0, 0] + sy = 0.0 # [0.1, 0., 0.] + + nouter, ninner = 500, 300 + hclose, rclose, relax = 1e-9, 1e-6, 1.0 + + tdis_rc = [] + for idx in range(nper): + tdis_rc.append((perlen[idx], nstp[idx], tsmult[idx])) + + # all cells are active + ib = 1 + + # chd data + c = [] + c6 = [] + ccol = [3, 4, 5, 6] + for j in ccol: + c.append([0, nrow - 1, j, strt, strt]) + c6.append([(0, nrow - 1, j), strt]) + cd = {0: c} + cd6 = {0: c6} + maxchd = len(cd[0]) + + # pumping well data + wr = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3] + wc = [0, 1, 8, 9, 0, 9, 0, 9, 0, 0] + wrp = [2, 2, 3, 3] + wcp = [5, 6, 5, 6] + wq = [-14000.0, -8000.0, -5000.0, -3000.0] + d = [] + d6 = [] + for r, c, q in zip(wrp, wcp, wq): + d.append([2, r, c, q]) + d6.append([(2, r, c), q]) + wd = {1: d} + wd6 = {1: d6} + maxwel = len(wd[1]) + + # recharge data + q = 3000.0 / (delr * delc) + v = np.zeros((nrow, ncol), dtype=float) + for r, c in zip(wr, wc): + v[r, c] = q + rech = {0: v} + + # static ibc and sub data + sgm = 0.0 + sgs = 0.0 + omega = 1.0 + void = 0.82 + theta = void / (1.0 + void) + sw = 4.65120000e-10 * 9806.65000000 * theta + + # no delay bed data + nndb = 3 + lnd = [0, 1, 2] + hc = [botm[-1] for k in range(nlay)] + thicknd0 = [zthick[0], zthick[1], zthick[2]] + ccnd0 = [6e-6, 3e-6, 6e-6] + crnd0 = [6e-6, 3e-6, 6e-6] + sfv = [] + sfe = [] + for k in range(nlay): + sfv.append(ccnd0[k] * thicknd0[k]) + sfe.append(crnd0[k] * thicknd0[k]) + + # sub output data + ds15 = [0, 0, 0, 2052, 0, 0, 0, 0, 0, 0, 0, 0] + ds16 = [0, nper - 1, 0, nstp[-1] - 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1] + + # build MODFLOW 6 files + sim = flopy.mf6.MFSimulation( + sim_name=name, version="mf6", exe_name="mf6", sim_ws=str(tmpdir) + ) + # create tdis package + tdis = flopy.mf6.ModflowTdis( + sim, time_units="DAYS", nper=nper, perioddata=tdis_rc + ) - csub_obs_package = csub.obs.initialize( - filename=opth, digits=10, print_input=True, continuous=orecarray - ) + # create iterative model solution + ims = flopy.mf6.ModflowIms( + sim, + print_option="SUMMARY", + outer_dvclose=hclose, + outer_maximum=nouter, + under_relaxation="NONE", + inner_maximum=ninner, + inner_dvclose=hclose, + rcloserecord=rclose, + linear_acceleration=imsla, + scaling_method="NONE", + reordering_method="NONE", + relaxation_factor=relax, + ) - # output control - oc = flopy.mf6.ModflowGwfoc( - gwf, - budget_filerecord=f"{name}.cbc", - head_filerecord=f"{name}.hds", - headprintrecord=[("COLUMNS", 10, "WIDTH", 15, "DIGITS", 6, "GENERAL")], - saverecord=[("HEAD", "ALL"), ("BUDGET", "ALL")], - printrecord=[("HEAD", "LAST"), ("BUDGET", "ALL")], - ) + # create gwf model + gwf = flopy.mf6.ModflowGwf( + sim, modelname=name, newtonoptions=newtonoptions + ) - return sim + dis = flopy.mf6.ModflowGwfdis( + gwf, + nlay=nlay, + nrow=nrow, + ncol=ncol, + delr=delr, + delc=delc, + top=data.top, + botm=botm, + filename=f"{name}.dis", + ) + # initial conditions + ic = flopy.mf6.ModflowGwfic(gwf, strt=strt, filename=f"{name}.ic") + + # node property flow + npf = flopy.mf6.ModflowGwfnpf( + gwf, + save_flows=False, + # dev_modflowusg_upstream_weighted_saturation=True, + icelltype=laytyp, + cvoptions=data.cvopt, + k=hk, + k33=vka, + ) + # storage + sto = flopy.mf6.ModflowGwfsto( + gwf, + save_flows=False, + iconvert=laytyp, + ss=0.0, + sy=sy, + storagecoefficient=True, + steady_state={0: True}, + transient={1: True}, + ) -# SUB package problem 3 -def build_model(idx, dir): - ws = dir - sim = get_model(idx, ws) + # recharge + rch = flopy.mf6.ModflowGwfrcha(gwf, readasarrays=True, recharge=rech) + + # wel file + wel = flopy.mf6.ModflowGwfwel( + gwf, + print_input=True, + print_flows=True, + maxbound=maxwel, + stress_period_data=wd6, + save_flows=False, + ) - ws = os.path.join(dir, cmppths[idx]) - mc = get_model(idx, ws) + # chd files + chd = flopy.mf6.modflow.mfgwfchd.ModflowGwfchd( + gwf, maxbound=maxchd, stress_period_data=cd6, save_flows=False + ) + # csub files + opth = f"{name}.csub.obs" + csub = flopy.mf6.ModflowGwfcsub( + gwf, + head_based=True, + save_flows=True, + ninterbeds=0, + cg_theta=theta, + cg_ske_cr=crnd0, + packagedata=None, + ) + obspos = [(0, 4, 4), (1, 4, 4), (2, 4, 4)] + obstype = ["compaction-cell", "csub-cell"] + obstag = ["tcomp", "csub"] + obsarr = [] + for iobs, cobs in enumerate(obstype): + for jobs, otup in enumerate(obspos): + otag = f"{obstag[iobs]}{jobs + 1}" + obsarr.append((otag, cobs, otup)) + + obsarr2 = [] + obstype2 = [ + "csub", + "inelastic-csub", + "elastic-csub", + "sk", + "ske", + "thickness", + "theta", + "interbed-compaction", + "inelastic-compaction", + "elastic-compaction", + "delay-flowtop", + "delay-flowbot", + ] + iobs = 0 + for cobs in obstype2: + iobs += 1 + otag = f"obs{iobs:03d}" + obsarr2.append((otag, cobs, (0,))) + + obstype3 = [ + "delay-preconstress", + "delay-head", + "delay-gstress", + "delay-estress", + "delay-compaction", + "delay-thickness", + "delay-theta", + ] + for cobs in obstype3: + iobs += 1 + otag = f"obs{iobs:03d}" + obsarr2.append((otag, cobs, (0,), (0,))) + + obsarr3 = [] + obstype4 = [ + "gstress-cell", + "estress-cell", + "thickness-cell", + "coarse-csub", + "wcomp-csub-cell", + "coarse-compaction", + "coarse-theta", + "coarse-thickness", + "csub-cell", + "ske-cell", + "sk-cell", + "theta-cell", + "compaction-cell", + ] + for cobs in obstype4: + iobs += 1 + otag = f"obs{iobs:03d}" + obsarr3.append((otag, cobs, obspos[-1])) + + orecarray = {} + orecarray["csub_obs.csv"] = obsarr + orecarray["interbed_obs.csv"] = obsarr2 + orecarray["coarse_cell_obs.csv"] = obsarr3 + + csub_obs_package = csub.obs.initialize( + filename=opth, digits=10, print_input=True, continuous=orecarray + ) - return sim, mc + # output control + oc = flopy.mf6.ModflowGwfoc( + gwf, + budget_filerecord=f"{name}.cbc", + head_filerecord=f"{name}.hds", + headprintrecord=[("COLUMNS", 10, "WIDTH", 15, "DIGITS", 6, "GENERAL")], + saverecord=[("HEAD", "ALL"), ("BUDGET", "ALL")], + printrecord=[("HEAD", "LAST"), ("BUDGET", "ALL")], + ) + return sim -def eval_comp(sim): - print("evaluating compaction...") + def eval_case(self, sim, data): + print("evaluating compaction...") - # MODFLOW 6 total compaction results - fpth = os.path.join(sim.simpath, "csub_obs.csv") - try: + # MODFLOW 6 total compaction results + fpth = os.path.join(sim.simpath, "csub_obs.csv") tc = np.genfromtxt(fpth, names=True, delimiter=",") - except: - assert False, f'could not load data from "{fpth}"' - # regression compaction results - cpth = cmppths[sim.idxsim] - fpth = os.path.join(sim.simpath, cpth, "csub_obs.csv") - try: + # regression compaction results + cpth = "mf6_regression" + fpth = os.path.join(sim.simpath, cpth, "csub_obs.csv") tc0 = np.genfromtxt(fpth, names=True, delimiter=",") - except: - assert False, f'could not load data from "{fpth}"' - - # calculate maximum absolute error - diff = tc["TCOMP3"] - tc0["TCOMP3"] - diffmax = np.abs(diff).max() - msg = f"maximum absolute total-compaction difference ({diffmax}) " - - # write summary - fpth = os.path.join( - sim.simpath, f"{os.path.basename(sim.name)}.comp.cmp.out" - ) - f = open(fpth, "w") - for i in range(diff.shape[0]): - line = f"{tc0['time'][i]:10.2g}" - line += f"{tc['TCOMP3'][i]:10.2g}" - line += f"{tc0['TCOMP3'][i]:10.2g}" - line += f"{diff[i]:10.2g}" - f.write(line + "\n") - f.close() - - if diffmax > dtol: - sim.success = False - msg += f"exceeds {dtol}" - assert diffmax < dtol, msg - else: - sim.success = True - print(" " + msg) - - # get results from listing file - fpth = os.path.join(sim.simpath, f"{os.path.basename(sim.name)}.lst") - budl = flopy.utils.Mf6ListBudget(fpth) - names = list(bud_lst) - d0 = budl.get_budget(names=names)[0] - dtype = d0.dtype - nbud = d0.shape[0] - - # get results from cbc file - cbc_bud = ["CSUB-CGELASTIC", "CSUB-WATERCOMP"] - d = np.recarray(nbud, dtype=dtype) - for key in bud_lst: - d[key] = 0.0 - fpth = os.path.join(sim.simpath, f"{os.path.basename(sim.name)}.cbc") - cobj = flopy.utils.CellBudgetFile(fpth, precision="double") - kk = cobj.get_kstpkper() - times = cobj.get_times() - for idx, (k, t) in enumerate(zip(kk, times)): - for text in cbc_bud: - qin = 0.0 - qout = 0.0 - v = cobj.get_data(kstpkper=k, text=text)[0] - for kk in range(v.shape[0]): - for ii in range(v.shape[1]): - for jj in range(v.shape[2]): - vv = v[kk, ii, jj] - if vv < 0.0: - qout -= vv - else: - qin += vv - d["totim"][idx] = t - d["time_step"][idx] = k[0] - d["stress_period"] = k[1] - key = f"{text}_IN" - d[key][idx] = qin - key = f"{text}_OUT" - d[key][idx] = qout - - diff = np.zeros((nbud, len(bud_lst)), dtype=float) - for idx, key in enumerate(bud_lst): - diff[:, idx] = d0[key] - d[key] - diffmax = np.abs(diff).max() - msg = f"maximum absolute total-budget difference ({diffmax}) " - - # write summary - fpth = os.path.join( - sim.simpath, f"{os.path.basename(sim.name)}.bud.cmp.out" - ) - f = open(fpth, "w") - for i in range(diff.shape[0]): - if i == 0: - line = f"{'TIME':>10s}" - for idx, key in enumerate(bud_lst): - line += f"{key + '_LST':>25s}" - line += f"{key + '_CBC':>25s}" - line += f"{key + '_DIF':>25s}" - f.write(line + "\n") - line = f"{d['totim'][i]:10g}" - for idx, key in enumerate(bud_lst): - line += f"{d0[key][i]:25g}" - line += f"{d[key][i]:25g}" - line += f"{diff[i, idx]:25g}" - f.write(line + "\n") - f.close() - - if diffmax > budtol: - sim.success = False - msg += f"exceeds {dtol}" - assert diffmax < dtol, msg - else: - sim.success = True - print(" " + msg) - - return - - -# - No need to change any code below - - -@pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), -) -def test_mf6model(idx, dir): - # determine if running on CI infrastructure - is_CI = running_on_CI() - r_exe = None - if not is_CI: - if replace_exe is not None: - r_exe = replace_exe - - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6( - Simulation( - dir, - exfunc=eval_comp, - htol=htol[idx], - idxsim=idx, - mf6_regression=True, - ) - ) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation( - dir, - exfunc=eval_comp, - htol=htol[idx], - idxsim=idx, - mf6_regression=True, - ) - test.run_mf6(sim) - return + # calculate maximum absolute error + diff = tc["TCOMP3"] - tc0["TCOMP3"] + diffmax = np.abs(diff).max() + msg = f"maximum absolute total-compaction difference ({diffmax}) " - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() + # write summary + fpth = os.path.join( + sim.simpath, f"{os.path.basename(sim.name)}.comp.cmp.out" + ) + f = open(fpth, "w") + for i in range(diff.shape[0]): + line = f"{tc0['time'][i]:10.2g}" + line += f"{tc['TCOMP3'][i]:10.2g}" + line += f"{tc0['TCOMP3'][i]:10.2g}" + line += f"{diff[i]:10.2g}" + f.write(line + "\n") + f.close() + + if diffmax > self.dtol: + sim.success = False + msg += f"exceeds {self.dtol}" + assert diffmax < self.dtol, msg + else: + sim.success = True + print(" " + msg) + + # get results from listing file + fpth = os.path.join(sim.simpath, f"{os.path.basename(sim.name)}.lst") + budl = flopy.utils.Mf6ListBudget(fpth) + names = list(self.bud_lst) + d0 = budl.get_budget(names=names)[0] + dtype = d0.dtype + nbud = d0.shape[0] + + # get results from cbc file + cbc_bud = ["CSUB-CGELASTIC", "CSUB-WATERCOMP"] + d = np.recarray(nbud, dtype=dtype) + for key in self.bud_lst: + d[key] = 0.0 + fpth = os.path.join(sim.simpath, f"{os.path.basename(sim.name)}.cbc") + cobj = flopy.utils.CellBudgetFile(fpth, precision="double") + kk = cobj.get_kstpkper() + times = cobj.get_times() + for idx, (k, t) in enumerate(zip(kk, times)): + for text in cbc_bud: + qin = 0.0 + qout = 0.0 + v = cobj.get_data(kstpkper=k, text=text)[0] + for kk in range(v.shape[0]): + for ii in range(v.shape[1]): + for jj in range(v.shape[2]): + vv = v[kk, ii, jj] + if vv < 0.0: + qout -= vv + else: + qin += vv + d["totim"][idx] = t + d["time_step"][idx] = k[0] + d["stress_period"] = k[1] + key = f"{text}_IN" + d[key][idx] = qin + key = f"{text}_OUT" + d[key][idx] = qout + + diff = np.zeros((nbud, len(self.bud_lst)), dtype=float) + for idx, key in enumerate(self.bud_lst): + diff[:, idx] = d0[key] - d[key] + diffmax = np.abs(diff).max() + msg = f"maximum absolute total-budget difference ({diffmax}) " + + # write summary + fpth = os.path.join( + sim.simpath, f"{os.path.basename(sim.name)}.bud.cmp.out" + ) + f = open(fpth, "w") + for i in range(diff.shape[0]): + if i == 0: + line = f"{'TIME':>10s}" + for idx, key in enumerate(self.bud_lst): + line += f"{key + '_LST':>25s}" + line += f"{key + '_CBC':>25s}" + line += f"{key + '_DIF':>25s}" + f.write(line + "\n") + line = f"{d['totim'][i]:10g}" + for idx, key in enumerate(self.bud_lst): + line += f"{d0[key][i]:25g}" + line += f"{d[key][i]:25g}" + line += f"{diff[i, idx]:25g}" + f.write(line + "\n") + f.close() + + if diffmax > self.budtol: + sim.success = False + msg += f"exceeds {self.dtol}" + assert diffmax < self.dtol, msg + else: + sim.success = True + print(" " + msg) + + +@parametrize_with_cases("case", cases=[ + GwfCsubSkCases, +]) +def test_mf6model(case, targets): + data, sim, cmp, evl = case + sim.write_simulation() + if cmp: cmp.write_simulation() + test = TestConfig(name=data.name, exes=targets, exfunc=evl, idxsim=0, mf6_regression=True) + test.set_model(sim.simulation_data.mfpath.get_sim_path(), testModel=False) + test.run() + test.compare() + evl(test, data) diff --git a/autotest/test_gwf_csub_sk02.py b/autotest/test_gwf_csub_sk02.py index d87765feed8..773fed17b01 100644 --- a/autotest/test_gwf_csub_sk02.py +++ b/autotest/test_gwf_csub_sk02.py @@ -3,50 +3,22 @@ import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import running_on_CI, testing_framework -from simulation import Simulation +import flopy +from conftest import is_in_ci + +from harness import TestHarness, TestConfig ex = ["csub_sk02a", "csub_sk02b", "csub_sk02c", "csub_sk02d"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -constantcv = [True for idx in range(len(exdirs))] - -cmppths = ["mf6-regression" for idx in range(len(exdirs))] -tops = [150.0 for idx in range(len(exdirs))] -newtons = [True for idx in range(len(exdirs))] +constantcv = [True for idx in range(len(ex))] +cmppths = ["mf6_regression" for idx in range(len(ex))] +tops = [150.0 for idx in range(len(ex))] +newtons = [True for idx in range(len(ex))] ump = [None, None, True, True] iump = [0, 0, 1, 1] -eslag = [True for idx in range(len(exdirs))] +eslag = [True for idx in range(len(ex))] icrcc = [0, 1, 0, 1] - -ddir = "data" - -## run all examples on Travis -continuous_integration = [True for idx in range(len(exdirs))] - -# set replace_exe to None to use default executable -replace_exe = None - -htol = [None for idx in range(len(exdirs))] +htol = [None for idx in range(len(ex))] dtol = 1e-3 - bud_lst = [ "CSUB-CGELASTIC_IN", "CSUB-CGELASTIC_OUT", @@ -481,71 +453,22 @@ def eval_comp(sim): sim.success = True print(" " + msg) - return - - -# - No need to change any code below - @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # determine if running on CI infrastructure - is_CI = running_on_CI() - r_exe = None - if not is_CI: - if replace_exe is not None: - r_exe = replace_exe - - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - if is_CI and not continuous_integration[idx]: - return - test.run_mf6( - Simulation( - dir, +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run( + TestConfig( + name=name, + exes=targets, exfunc=eval_comp, - exe_dict=r_exe, htol=htol[idx], idxsim=idx, mf6_regression=True, - ) + ), + str(function_tmpdir) ) - - return - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation( - dir, - exfunc=eval_comp, - exe_dict=replace_exe, - htol=htol[idx], - idxsim=idx, - mf6_regression=True, - ) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_csub_sk03.py b/autotest/test_gwf_csub_sk03.py index ce7e9e7685c..978edaedd6f 100644 --- a/autotest/test_gwf_csub_sk03.py +++ b/autotest/test_gwf_csub_sk03.py @@ -1,50 +1,19 @@ import datetime import os +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import running_on_CI, testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["csub_sk03a"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -constantcv = [True for idx in range(len(exdirs))] - -cmppths = ["mf6-regression" for idx in range(len(exdirs))] -newtons = [True for idx in range(len(exdirs))] - +constantcv = [True for idx in range(len(ex))] +cmppths = ["mf6_regression" for idx in range(len(ex))] +newtons = [True for idx in range(len(ex))] icrcc = [0, 1, 0, 1] - -ddir = "data" - -## run all examples on Travis -continuous_integration = [True for idx in range(len(exdirs))] - -# set replace_exe to None to use default executable -replace_exe = None - -htol = [None for idx in range(len(exdirs))] +htol = [None for idx in range(len(ex))] dtol = 1e-3 - bud_lst = [ "CSUB-CGELASTIC_IN", "CSUB-CGELASTIC_OUT", @@ -628,70 +597,23 @@ def eval_comp(sim): sim.success = True print(" " + msg) - return - - -# - No need to change any code below - +@pytest.mark.slow @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # determine if running on CI infrastructure - is_CI = running_on_CI() - r_exe = None - if not is_CI: - if replace_exe is not None: - r_exe = replace_exe - - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - if is_CI and not continuous_integration[idx]: - return - test.run_mf6( - Simulation( - dir, +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run( + TestConfig( + name=name, + exes=targets, exfunc=eval_comp, - exe_dict=r_exe, htol=htol[idx], idxsim=idx, mf6_regression=True, - ) + ), + str(function_tmpdir) ) - - return - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation( - dir, - exfunc=eval_comp, - exe_dict=replace_exe, - htol=htol[idx], - idxsim=idx, - mf6_regression=True, - ) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_csub_sk04_nr.py b/autotest/test_gwf_csub_sk04_nr.py index 5ba5545ee75..a90222fe4ee 100644 --- a/autotest/test_gwf_csub_sk04_nr.py +++ b/autotest/test_gwf_csub_sk04_nr.py @@ -1,26 +1,10 @@ import os +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import running_on_CI, testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ( "csub_sk04a", @@ -28,9 +12,6 @@ "csub_sk04c", "csub_sk04d", ) -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) newtons = (True, False, True, False) stress_lag = ( None, @@ -39,11 +20,6 @@ True, ) -ddir = "data" - -# set replace_exe to None to use default executable -replace_exe = None - htol = None dtol = 1e-3 budtol = 0.01 @@ -351,54 +327,21 @@ def eval_comp(sim): sim.success = True print(" " + msg) - return - - -# - No need to change any code below - @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # determine if running on CI infrastructure - is_CI = running_on_CI() - r_exe = None - if not is_CI: - if replace_exe is not None: - r_exe = replace_exe - - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6( - Simulation( - dir, exfunc=eval_comp, exe_dict=r_exe, htol=htol, idxsim=idx - ) +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run( + TestConfig( + name=name, + exes=targets, + exfunc=eval_comp, + htol=htol, + idxsim=idx + ), + str(function_tmpdir) ) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation( - dir, exfunc=eval_comp, exe_dict=replace_exe, htol=htol, idxsim=idx - ) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_csub_sub01.py b/autotest/test_gwf_csub_sub01.py index 5302a6ae736..6d8e95c42f0 100644 --- a/autotest/test_gwf_csub_sub01.py +++ b/autotest/test_gwf_csub_sub01.py @@ -3,47 +3,16 @@ import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import running_on_CI, testing_framework -from simulation import Simulation +import flopy + +from harness import TestHarness, TestConfig paktest = "csub" budtol = 1e-2 - ex = ["csub_sub01a", "csub_sub01b"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" - compression_indices = [None, True] - ndcell = [19] * len(ex) -# run all examples on Travis -# continuous_integration = [True for idx in range(len(exdirs))] -# the delay bed problems only run on the development version of MODFLOW-2005 -# set travis to True when version 1.13.0 is released -continuous_integration = [True for idx in range(len(exdirs))] - -# set replace_exe to None to use default executable -replace_exe = None - # static model data # spatial discretization nlay, nrow, ncol = 1, 1, 3 @@ -254,7 +223,7 @@ def build_model(idx, dir): sim = get_model(idx, ws) # build MODFLOW-2005 files - ws = os.path.join(dir, "mf6-regression") + ws = os.path.join(dir, "mf6_regression") mc = get_model(idx, ws) return sim, mc @@ -271,7 +240,7 @@ def eval_sub(sim): assert False, f'could not load data from "{fpth}"' # comparison total compaction results - fpth = os.path.join(sim.simpath, "mf6-regression", "csub_obs.csv") + fpth = os.path.join(sim.simpath, "mf6_regression", "csub_obs.csv") try: tc0 = np.genfromtxt(fpth, names=True, delimiter=",") except: @@ -409,50 +378,21 @@ def cbc_compare(sim): sim.success = True print(" " + msg) - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, exdir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, exdir): - # initialize testing framework - test = testing_framework() - - # run the test model - test.build_mf6_models(build_model, idx, exdir) - - test.run_mf6( - Simulation( - exdir, +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run( + TestConfig( + name=name, + exes=targets, exfunc=eval_sub, idxsim=idx, mf6_regression=True, - ) + ), + str(function_tmpdir) ) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, exdir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, exdir) - sim = Simulation( - exdir, - exfunc=eval_sub, - idxsim=idx, - mf6_regression=True, - ) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_csub_sub01_adjmat.py b/autotest/test_gwf_csub_sub01_adjmat.py index de5c09ca06b..725938dcab2 100644 --- a/autotest/test_gwf_csub_sub01_adjmat.py +++ b/autotest/test_gwf_csub_sub01_adjmat.py @@ -3,48 +3,18 @@ import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import running_on_CI, testing_framework -from simulation import Simulation +import flopy + +from harness import TestHarness, TestConfig paktest = "csub" budtol = 1e-2 compdir = "mf6" ex = ["csub_sub01_adj"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" - compression_indices = [None] - ndcell = [19] * len(ex) -# run all examples on Travis -# continuous_integration = [True for idx in range(len(exdirs))] -# the delay bed problems only run on the development version of MODFLOW-2005 -# set travis to True when version 1.13.0 is released -continuous_integration = [True for idx in range(len(exdirs))] - -# set replace_exe to None to use default executable -replace_exe = None - # static model data # spatial discretization nlay, nrow, ncol = 1, 1, 3 @@ -327,8 +297,8 @@ def eval_sub(sim): # calculate theta and porosity from interbed cell compaction calci = np.zeros((comp.shape[0]), dtype=dtype) - thickini = 1.0 / ndcell[sim.idxsim] - for n in range(ndcell[sim.idxsim]): + thickini = 1.0 / ndcell[0] + for n in range(ndcell[0]): tagc = f"DBCOMP{n + 1:02d}" tagb = f"DBTHICK{n + 1:02d}" tagp = f"DBPORO{n + 1:02d}" @@ -378,8 +348,6 @@ def eval_sub(sim): # compare budgets cbc_compare(sim) - return - # compare cbc and lst budgets def cbc_compare(sim): @@ -467,6 +435,8 @@ def cbc_compare(sim): f.write(line + "\n") f.close() + dtol = 1e-6 + if diffmax > budtol: sim.success = False msg += f"exceeds {dtol}" @@ -475,54 +445,9 @@ def cbc_compare(sim): sim.success = True print(" " + msg) - return - - -# - No need to change any code below - - -@pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), -) -def test_mf6model(idx, dir): - # determine if running on CI infrastructure - is_CI = running_on_CI() - r_exe = None - if not is_CI: - if replace_exe is not None: - r_exe = replace_exe - - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - if is_CI and not continuous_integration[idx]: - return - test.run_mf6(Simulation(dir, exfunc=eval_sub, exe_dict=r_exe, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation( - dir, exfunc=eval_sub, exe_dict=replace_exe, idxsim=idx - ) - test.run_mf6(sim) - return - - -# use python testmf6_csub_sub01.py --mf2005 mf2005devdbl -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - # run main routine - main() +@pytest.mark.parametrize("name", ex) +def test_mf6model(name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, 0, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_sub, idxsim=0), str(function_tmpdir)) diff --git a/autotest/test_gwf_csub_sub01_elastic.py b/autotest/test_gwf_csub_sub01_elastic.py index baec5b1bfe5..9c000fc2893 100644 --- a/autotest/test_gwf_csub_sub01_elastic.py +++ b/autotest/test_gwf_csub_sub01_elastic.py @@ -1,47 +1,18 @@ import os +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import running_on_CI, testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig cmppth = "mf6" - paktest = "csub" dtol = 1e-3 budtol = 1e-2 - ex = ["csub_sub01_elasa"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" - ndcell = [19] -# run all examples on Travis -continuous_integration = [True for idx in range(len(exdirs))] - -# set replace_exe to None to use default executable -replace_exe = None - # static model data # spatial discretization nlay, nrow, ncol = 1, 1, 3 @@ -371,51 +342,12 @@ def cbc_compare(sim): sim.success = True print(" " + msg) - return - - -# - No need to change any code below - @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # determine if running on CI infrastructure - is_CI = running_on_CI() - r_exe = None - if not is_CI: - if replace_exe is not None: - r_exe = replace_exe - - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - if is_CI and not continuous_integration[idx]: - return - test.run_mf6(Simulation(dir, exfunc=eval_sub, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_sub, idxsim=idx) - test.run_mf6(sim) - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_sub, idxsim=idx), str(function_tmpdir)) diff --git a/autotest/test_gwf_csub_sub01_pch.py b/autotest/test_gwf_csub_sub01_pch.py index 73632cf0efb..db0ecda629c 100644 --- a/autotest/test_gwf_csub_sub01_pch.py +++ b/autotest/test_gwf_csub_sub01_pch.py @@ -1,48 +1,17 @@ import os +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import running_on_CI, testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig paktest = "csub" budtol = 1e-2 - compdir = "mf6" ex = ["csub_sub01_pch"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" - ndcell = [19] * len(ex) -# run all examples on Travis -# continuous_integration = [True for idx in range(len(exdirs))] -# the delay bed problems only run on the development version of MODFLOW-2005 -# set travis to True when version 1.13.0 is released -continuous_integration = [True for idx in range(len(exdirs))] - -# set replace_exe to None to use default executable -replace_exe = None - # static model data # spatial discretization nlay, nrow, ncol = 1, 1, 3 @@ -304,8 +273,6 @@ def eval_sub(sim): # compare budgets cbc_compare(sim) - return - # compare cbc and lst budgets def cbc_compare(sim): @@ -393,6 +360,8 @@ def cbc_compare(sim): f.write(line + "\n") f.close() + dtol = 1e-6 + if diffmax > budtol: sim.success = False msg += f"exceeds {dtol}" @@ -402,50 +371,11 @@ def cbc_compare(sim): print(" " + msg) -# - No need to change any code below - - @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # determine if running on CI infrastructure - is_CI = running_on_CI() - r_exe = None - if not is_CI: - if replace_exe is not None: - r_exe = replace_exe - - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - if is_CI and not continuous_integration[idx]: - return - test.run_mf6(Simulation(dir, exfunc=eval_sub, exe_dict=r_exe, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation( - dir, exfunc=eval_sub, exe_dict=replace_exe, idxsim=idx - ) - test.run_mf6(sim) - - -# use python testmf6_csub_sub01.py --mf2005 mf2005devdbl -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_sub, idxsim=idx), str(function_tmpdir)) diff --git a/autotest/test_gwf_csub_sub02.py b/autotest/test_gwf_csub_sub02.py index 858bfb6d241..b176cb5a4fb 100644 --- a/autotest/test_gwf_csub_sub02.py +++ b/autotest/test_gwf_csub_sub02.py @@ -2,24 +2,9 @@ import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) +import flopy -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import running_on_CI, testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = [ "csub_sub02a", @@ -28,12 +13,7 @@ "csub_sub02d", "csub_sub02e", ] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" -cmppth = "mf6-regression" - +cmppth = "mf6_regression" cg_ske = 1.14e-3 / (500.0 - 20.0) cg_S = cg_ske * (500.0 - 20.0) ss = [cg_S, cg_S, cg_ske, cg_ske, cg_S] @@ -41,12 +21,6 @@ cdelay = [False, True, False, True, True] ndelaycells = [None, 19, None, 19, 19] -# run all examples on Travis -continuous_integration = [True for e in ex] - -# set replace_exe to None to use default executable -replace_exe = None - # static model data nlay, nrow, ncol = 1, 1, 1 nper = 10 @@ -236,50 +210,11 @@ def build_model(idx, dir): return sim, mc -# - No need to change any code below - - @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # determine if running on CI infrastructure - is_CI = running_on_CI() - - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - if is_CI and not continuous_integration[idx]: - return - - # run the test model - test.run_mf6(Simulation(dir, mf6_regression=True)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for dir in exdirs: - test.build_mf6_models(build_model, idx, dir) - sim = Simulation( - dir, - mf6_regression=True, - ) - test.run_mf6(sim) - - return - - -# use python test_gwf_csub_sub02.py --mf2005 mf2005devdbl -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, mf6_regression=True), str(function_tmpdir)) diff --git a/autotest/test_gwf_csub_sub03.py b/autotest/test_gwf_csub_sub03.py index 67b3ab36e5b..461b3165b40 100644 --- a/autotest/test_gwf_csub_sub03.py +++ b/autotest/test_gwf_csub_sub03.py @@ -1,50 +1,20 @@ import os +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import running_on_CI, testing_framework -from simulation import Simulation +from conftest import get_project_root_path +from harness import TestHarness, TestConfig ex = ["csub_sub03a", "csub_sub03b"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -cmppth = "mf6-regression" - - +cmppth = "mf6_regression" cvopt = [None, None, None] constantcv = [True, True] ndelaybeds = [0, 2] ndelaycells = [None, 39] - -ddir = "data" - -## run all examples on Travis -continuous_integration = [True for e in ex] - -# set replace_exe to None to use default executable -replace_exe = None - htol = [None, None, None] dtol = 1e-3 - bud_lst = [ "CSUB-ELASTIC_IN", "CSUB-INELASTIC_IN", @@ -161,7 +131,7 @@ nz = [1, 1] dstart = [] for k in ldnd: - pth = os.path.join(ddir, f"ibc03_dstart{k + 1}.ref") + pth = str(get_project_root_path() / "autotest" / "data" / f"ibc03_dstart{k + 1}.ref") v = np.genfromtxt(pth) dstart.append(v.copy()) @@ -461,62 +431,22 @@ def eval_comp(sim): sim.success = True print(" " + msg) - return - - -# - No need to change any code below - +@pytest.mark.slow @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # determine if running on CI infrastructure - is_CI = running_on_CI() - - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - if is_CI and not continuous_integration[idx]: - return - test.run_mf6( - Simulation( - dir, +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run( + TestConfig( + name=name, + exes=targets, exfunc=eval_comp, htol=htol[idx], mf6_regression=True, - ) + ), + str(function_tmpdir) ) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation( - dir, - exfunc=eval_comp, - mf6_regression=True, - htol=htol[idx], - ) - test.run_mf6(sim) - - return - - -# use python test_gwf_csub_sub03.py --mf2005 mf2005devdbl -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_csub_subwt01.py b/autotest/test_gwf_csub_subwt01.py index b4fb615e35c..20a63596f96 100644 --- a/autotest/test_gwf_csub_subwt01.py +++ b/autotest/test_gwf_csub_subwt01.py @@ -1,51 +1,21 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import running_on_CI, testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["csub_subwt01a", "csub_subwt01b", "csub_subwt01c", "csub_subwt01d"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" -cmppth = "mf6-regression" - +cmppth = "mf6_regression" htol = [None for n in ex] dtol = 1e-3 budtol = 1e-2 - paktest = "csub" - ump = [None, True, None, True] ivoid = [0, 1, 0, 1] gs0 = [0.0, 0.0, 1700.0, 1700.0] -# set travis to True when version 1.13.0 is released -continuous_integration = [True for n in ex] - -# set replace_exe to None to use default executable -replace_exe = None - # temporal discretization nper = 3 perlen = [1.0, 21915.0, 21915.0] @@ -432,67 +402,22 @@ def cbc_compare(sim): sim.success = True print(" " + msg) - return - - -# - No need to change any code below - +@pytest.mark.slow @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # determine if running on CI infrastructure - is_CI = running_on_CI() - r_exe = None - if not is_CI: - if replace_exe is not None: - r_exe = replace_exe - - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - if is_CI and not continuous_integration[idx]: - return - test.run_mf6( - Simulation( - dir, - exe_dict=r_exe, +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run( + TestConfig( + name=name, + exes=targets, exfunc=eval_comp, htol=htol[idx], mf6_regression=True, - ) + ), + str(function_tmpdir) ) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for dir in exdirs: - test.build_mf6_models(build_model, idx, dir) - sim = Simulation( - dir, - exe_dict=replace_exe, - exfunc=eval_comp, - htol=htol[idx], - mf6_regression=True, - ) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_csub_subwt02.py b/autotest/test_gwf_csub_subwt02.py index 399390f0bdb..3113d462b6a 100644 --- a/autotest/test_gwf_csub_subwt02.py +++ b/autotest/test_gwf_csub_subwt02.py @@ -1,53 +1,25 @@ import os +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import running_on_CI, testing_framework -from simulation import Simulation +from conftest import get_project_root_path +from harness import TestHarness, TestConfig ex = ["csub_subwt02a", "csub_subwt02b", "csub_subwt02c", "csub_subwt02d"] timeseries = [True, False, True, False] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" -cmppth = "mf6-regression" - +cmppth = "mf6_regression" htol = [None, None, None, None] dtol = 1e-3 budtol = 1e-2 - paktest = "csub" - ump = [None, True, None, True] ivoid = [0, 1, 0, 1] gs0 = [0.0, 0.0, 1700.0, 1700.0] -# set travis to True when version 1.13.0 is released -continuous_integration = [True, True, True, True] - -# set replace_exe to None to use default executable -replace_exe = None - # static model data -pth = os.path.join(ddir, "ibc01_ibound.ref") +pth = str(get_project_root_path() / "autotest" / "data" / "ibc01_ibound.ref") ib0 = np.genfromtxt(pth) # temporal discretization @@ -598,67 +570,22 @@ def cbc_compare(sim): sim.success = True print(" " + msg) - return - - -# - No need to change any code below - +@pytest.mark.slow @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # determine if running on CI infrastructure - is_CI = running_on_CI() - r_exe = None - if not is_CI: - if replace_exe is not None: - r_exe = replace_exe - - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - if is_CI and not continuous_integration[idx]: - return - test.run_mf6( - Simulation( - dir, - exe_dict=r_exe, +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run( + TestConfig( + name=name, + exes=targets, exfunc=eval_comp, htol=htol[idx], mf6_regression=True, - ) + ), + str(function_tmpdir) ) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for dir in exdirs: - test.build_mf6_models(build_model, idx, dir) - sim = Simulation( - dir, - exe_dict=replace_exe, - exfunc=eval_comp, - htol=htol[idx], - mf6_regression=True, - ) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_csub_subwt03.py b/autotest/test_gwf_csub_subwt03.py index 85649fa11fa..cc78436f322 100644 --- a/autotest/test_gwf_csub_subwt03.py +++ b/autotest/test_gwf_csub_subwt03.py @@ -1,53 +1,25 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import running_on_CI, testing_framework -from simulation import Simulation +from conftest import get_project_root_path +from harness import TestHarness, TestConfig ex = ["csub_subwt03a", "csub_subwt03b", "csub_subwt03c", "csub_subwt03d"] nex = len(ex) -exdirs = [os.path.join("temp", s) for s in ex] - -ddir = "data" cmppth = "mf6" - htol = None # 0.1 dtol = 1e-3 budtol = 1e-2 - paktest = "csub" - isnewton = 2 * [None, "NEWTON"] headbased = [True, True, False, False] delay = 4 * [False] -# set travis to True when version 1.13.0 is released -continuous_integration = [True for s in ex] - -# set replace_exe to None to use default executable -replace_exe = None - # static model data -pth = os.path.join(ddir, "ibc01_ibound.ref") +pth = str(get_project_root_path() / "autotest" / "data" / "ibc01_ibound.ref") ib0 = np.genfromtxt(pth) # temporal discretization @@ -440,8 +412,6 @@ def eval_comp(sim): # compare budgets cbc_compare(sim) - return - # compare cbc and lst budgets def cbc_compare(sim): @@ -538,64 +508,19 @@ def cbc_compare(sim): sim.success = True print(" " + msg) - return - - -# - No need to change any code below - +@pytest.mark.slow @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # determine if running on CI infrastructure - is_CI = running_on_CI() - r_exe = None - if not is_CI: - if replace_exe is not None: - r_exe = replace_exe - - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - if is_CI and not continuous_integration[idx]: - return - test.run_mf6( - Simulation( - dir, exe_dict=r_exe, exfunc=eval_comp, cmp_verbose=False, htol=htol - ) +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run( + TestConfig( + name=name, exes=targets, exfunc=eval_comp, cmp_verbose=False, htol=htol + ), + ws ) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for dir in exdirs: - test.build_mf6_models(build_model, idx, dir) - sim = Simulation( - dir, - exe_dict=replace_exe, - exfunc=eval_comp, - cmp_verbose=False, - htol=htol, - ) - test.run_mf6(sim) - - return - - -# use python testmf6_csub_subwt03.py -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_csub_wc01.py b/autotest/test_gwf_csub_wc01.py index de266afaade..584ddbd68a1 100644 --- a/autotest/test_gwf_csub_wc01.py +++ b/autotest/test_gwf_csub_wc01.py @@ -1,49 +1,21 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import running_on_CI, testing_framework -from simulation import Simulation +from conftest import get_project_root_path +from harness import TestHarness, TestConfig ex = ["csub_wc01a", "csub_wc02b"] -exdirs = [os.path.join("temp", s) for s in ex] - -ddir = "data" cmppth = "mf6" - dtol = 1e-3 budtol = 1e-2 - paktest = "csub" - isnewton = [None, "NEWTON"] -# set travis to True when version 1.13.0 is released -continuous_integration = [True for s in ex] - -# set replace_exe to None to use default executable -replace_exe = None - # static model data -pth = os.path.join(ddir, "ibc01_ibound.ref") +pth = str(get_project_root_path() / "autotest" / "data" / "ibc01_ibound.ref") ib0 = np.genfromtxt(pth) # temporal discretization @@ -531,51 +503,12 @@ def cbc_compare(sim): print(" " + msg) -# - No need to change any code below - - +@pytest.mark.slow @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # determine if running on CI infrastructure - is_CI = running_on_CI() - r_exe = None - if not is_CI: - if replace_exe is not None: - r_exe = replace_exe - - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - if is_CI and not continuous_integration[idx]: - return - test.run_mf6(Simulation(dir, exe_dict=r_exe, exfunc=eval_wcomp)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for dir in exdirs: - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exe_dict=replace_exe, exfunc=eval_wcomp) - test.run_mf6(sim) - - return - - -# main -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_wcomp), str(function_tmpdir)) diff --git a/autotest/test_gwf_csub_wtgeo.py b/autotest/test_gwf_csub_wtgeo.py index be59a6d0535..93e1ad071e3 100644 --- a/autotest/test_gwf_csub_wtgeo.py +++ b/autotest/test_gwf_csub_wtgeo.py @@ -3,24 +3,9 @@ import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import running_on_CI, testing_framework -from simulation import Simulation +import flopy + +from harness import TestHarness, TestConfig ex = [ "csub_wtgeoa", @@ -31,31 +16,19 @@ "csub_wtgeof", "csub_wtgeog", ] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -constantcv = [True for idx in range(len(exdirs))] - -cmppth = "mf6-regression" -compare = [True for idx in range(len(exdirs))] +constantcv = [True for idx in range(len(ex))] +cmppth = "mf6_regression" +compare = [True for idx in range(len(ex))] tops = [0.0, 0.0, 150.0, 0.0, 0.0, 150.0, 150.0] ump = [None, None, True, None, True, None, True] iump = [0, 0, 1, 0, 1, 0, 1] -eslag = [True for idx in range(len(exdirs) - 2)] + 2 * [False] +eslag = [True for idx in range(len(ex) - 2)] + 2 * [False] # eslag = [True, True, True, False, True, False, False] headformulation = [True, False, False, True, True, False, False] ndc = [None, None, None, 19, 19, 19, 19] delay = [False, False, False, True, True, True, True] # newton = ["", "", "", "", "", None, ""] -newton = ["NEWTON" for idx in range(len(exdirs))] - -ddir = "data" - -## run all examples on Travis -continuous_integration = [True for idx in range(len(exdirs))] - -# set replace_exe to None to use default executable -replace_exe = None +newton = ["NEWTON" for idx in range(len(ex))] htol = [None, None, None, 0.2, None, None, None] dtol = 1e-3 @@ -501,15 +474,8 @@ def get_model(idx, ws): def build_model(idx, dir): - - # build MODFLOW 6 files - ws = dir - sim = get_model(idx, ws) - - # build comparision files - ws = os.path.join(dir, cmppth) - mc = get_model(idx, ws) - + sim = get_model(idx, dir) # modflow6 files + mc = get_model(idx, os.path.join(dir, cmppth)) # build comparison files return sim, mc @@ -568,7 +534,6 @@ def eval_comp(sim): return -# compare cbc and lst budgets def cbc_compare(sim): print("evaluating cbc and budget...") # open cbc file @@ -663,71 +628,21 @@ def cbc_compare(sim): sim.success = True print(" " + msg) - return - - -# - No need to change any code below - -@pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), -) -def test_mf6model(idx, dir): - # determine if running on CI infrastructure - is_CI = running_on_CI() - r_exe = None - if not is_CI: - if replace_exe is not None: - r_exe = replace_exe - - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - if is_CI and not continuous_integration[idx]: - return - test.run_mf6( - Simulation( - dir, +@pytest.mark.slow +@pytest.mark.parametrize("idx, name", list(enumerate(ex))) +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run( + TestConfig( + name=name, + exes=targets, exfunc=eval_comp, - exe_dict=r_exe, htol=htol[idx], idxsim=idx, mf6_regression=True, - ) + ), + ws ) - - return - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation( - dir, - exfunc=eval_comp, - exe_dict=replace_exe, - htol=htol[idx], - idxsim=idx, - mf6_regression=True, - ) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_csub_zdisp01.py b/autotest/test_gwf_csub_zdisp01.py index d5ac7645d3b..9ec3f32c2d6 100644 --- a/autotest/test_gwf_csub_zdisp01.py +++ b/autotest/test_gwf_csub_zdisp01.py @@ -1,46 +1,17 @@ import os +import flopy import numpy as np import pytest +from flopy.utils.compare import compare_heads -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -from framework import running_on_CI, testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["csub_zdisp01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) - cmppth = "mfnwt" - -ddir = "data" - -## run all examples on Travis -continuous_integration = [True for idx in range(len(exdirs))] - -# set replace_exe to None to use default executable -replace_exe = None - -htol = [None for idx in range(len(exdirs))] +htol = [None for idx in range(len(ex))] dtol = 1e-3 budtol = 1e-2 - bud_lst = [ "STO-SS_IN", "STO-SS_OUT", @@ -421,15 +392,11 @@ def get_model(idx, dir): backflag=0, idroptol=0, ) - return sim, mc + sim.write_simulation() + mc.write_input() -def build_models(): - for idx, dir in enumerate(exdirs): - sim, mc = get_model(idx, dir) - sim.write_simulation() - mc.write_input() - return + return sim, mc def eval_zdisplacement(sim): @@ -561,7 +528,7 @@ def eval_zdisplacement(sim): sim.simpath, f"{os.path.basename(sim.name)}.z-displacement.bin.out", ) - success_tst = pymake.compare_heads( + success_tst = compare_heads( None, None, text=text1, @@ -581,66 +548,22 @@ def eval_zdisplacement(sim): sim.success = False assert success_tst, msg - return - -# - No need to change any code below +@pytest.mark.slow @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # determine if running on CI infrastructure - is_CI = running_on_CI() - r_exe = None - if not is_CI: - if replace_exe is not None: - r_exe = replace_exe - - # initialize testing framework - test = testing_framework() - - # build the models - build_models() - - # run the test model - if is_CI and not continuous_integration[idx]: - return - test.run_mf6( - Simulation( - dir, +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + sim, mc = get_model(idx, str(function_tmpdir)) + test.run( + TestConfig( + name=name, + exes=targets, exfunc=eval_zdisplacement, - exe_dict=r_exe, htol=htol[idx], idxsim=idx, - ) + ), + str(function_tmpdir) ) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - build_models() - - # run the test model - for idx, dir in enumerate(exdirs): - sim = Simulation( - dir, - exfunc=eval_zdisplacement, - exe_dict=replace_exe, - htol=htol[idx], - idxsim=idx, - ) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_disu01.py b/autotest/test_gwf_disu.py similarity index 61% rename from autotest/test_gwf_disu01.py rename to autotest/test_gwf_disu.py index 6adc1d59f77..85880b95d82 100644 --- a/autotest/test_gwf_disu01.py +++ b/autotest/test_gwf_disu.py @@ -1,54 +1,13 @@ -""" -MODFLOW 6 Autotest -Test to make sure that disu is working correctly - -""" - import os -import shutil -import subprocess +import flopy import numpy as np +from flopy.utils.gridutil import get_disu_kwargs -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -import targets -from framework import set_teardown_test - -mf6_exe = os.path.abspath(targets.target_dict["mf6"]) -testname = "gwf_disu01" -testdir = os.path.join("temp", testname) -everything_was_successful = True - -teardown_test = set_teardown_test() - - -def run_mf6(argv, ws): - buff = [] - proc = subprocess.Popen( - argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=ws - ) - result, error = proc.communicate() - if result is not None: - c = result.decode("utf-8") - c = c.rstrip("\r\n") - print(f"{c}") - buff.append(c) - - return proc.returncode, buff - - -def test_disu_simple(): - from disu_util import get_disu_kwargs +def test_disu_simple(tmpdir, targets): + mf6 = targets["mf6"] name = "disu01a" - ws = f"{testdir}_{name}" nlay = 3 nrow = 3 ncol = 3 @@ -58,7 +17,7 @@ def test_disu_simple(): botm = [-10, -20, -30] disukwargs = get_disu_kwargs(nlay, nrow, ncol, delr, delc, top, botm) sim = flopy.mf6.MFSimulation( - sim_name=name, version="mf6", exe_name=mf6_exe, sim_ws=ws + sim_name=name, version="mf6", exe_name=mf6, sim_ws=str(tmpdir) ) tdis = flopy.mf6.ModflowTdis(sim) gwf = flopy.mf6.ModflowGwf(sim, modelname=name) @@ -70,16 +29,11 @@ def test_disu_simple(): chd = flopy.mf6.modflow.mfgwfchd.ModflowGwfchd(gwf, stress_period_data=spd) sim.write_simulation() sim.run_simulation() - if teardown_test: - shutil.rmtree(ws, ignore_errors=True) - return - -def test_disu_idomain_simple(): - from disu_util import get_disu_kwargs +def test_disu_idomain_simple(tmpdir, targets): + mf6 = targets["mf6"] name = "disu01b" - ws = f"{testdir}_{name}" nlay = 3 nrow = 3 ncol = 3 @@ -92,7 +46,7 @@ def test_disu_idomain_simple(): disukwargs = get_disu_kwargs(nlay, nrow, ncol, delr, delc, top, botm) disukwargs["idomain"] = idomain sim = flopy.mf6.MFSimulation( - sim_name=name, version="mf6", exe_name=mf6_exe, sim_ws=ws + sim_name=name, version="mf6", exe_name=mf6, sim_ws=str(tmpdir) ) tdis = flopy.mf6.ModflowTdis(sim) gwf = flopy.mf6.ModflowGwf(sim, modelname=name, save_flows=True) @@ -112,7 +66,7 @@ def test_disu_idomain_simple(): sim.run_simulation() # check binary grid file - fname = os.path.join(ws, name + ".disu.grb") + fname = os.path.join(str(tmpdir), name + ".disu.grb") grbobj = flopy.mf6.utils.MfGrdFile(fname) nodes = grbobj._datadict["NODES"] ia = grbobj._datadict["IA"] @@ -125,24 +79,13 @@ def test_disu_idomain_simple(): assert ja.shape[0] == 126, "ja should have size of 126" # load head array and ensure nodata value in second cell - fname = os.path.join(ws, name + ".hds") + fname = os.path.join(str(tmpdir), name + ".hds") hdsobj = flopy.utils.HeadFile(fname) head = hdsobj.get_alldata().flatten() assert head[1] == 1.0e30 # load flowja to make sure it is the right size - fname = os.path.join(ws, name + ".bud") + fname = os.path.join(str(tmpdir), name + ".bud") budobj = flopy.utils.CellBudgetFile(fname, precision="double") flowja = budobj.get_data(text="FLOW-JA-FACE")[0].flatten() assert flowja.shape[0] == 126 - if teardown_test: - shutil.rmtree(ws, ignore_errors=True) - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - test_disu_simple() - test_disu_idomain_simple() diff --git a/autotest/test_gwf_disv_uzf.py b/autotest/test_gwf_disv_uzf.py index a4dcd4d8be1..e52ae634cb5 100644 --- a/autotest/test_gwf_disv_uzf.py +++ b/autotest/test_gwf_disv_uzf.py @@ -10,28 +10,14 @@ import os import pytest -import sys import numpy as np -try: - import flopy - import flopy.utils.cvfdutil -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - - -from framework import testing_framework -from simulation import Simulation +import flopy +import flopy.utils.cvfdutil +from harness import TestHarness, TestConfig ex = ["disv_with_uzf"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) - nlay = 5 nper = 5 perlen = [10] * 5 @@ -39,10 +25,8 @@ tsmult = len(perlen) * [1.0] botm = [20.0, 15.0, 10.0, 5.0, 0.0] strt = 20 - nouter, ninner = 100, 300 hclose, rclose, relax = 1e-9, 1e-3, 0.97 - ghb_ids = [] @@ -332,18 +316,14 @@ def build_model(idx, dir): def eval_model(sim): print("evaluating model...") - idx = sim.idxsim - name = ex[idx] - ws = os.path.join("temp", name) - # Next, get the binary printed heads - fpth = os.path.join(ws, name + ".hds") + fpth = os.path.join(sim.simpath, sim.name + ".hds") hobj = flopy.utils.HeadFile(fpth, precision="double") hds = hobj.get_alldata() hds = hds.reshape((np.sum(nstp), 5, 10, 10)) # Get the MF6 cell-by-cell fluxes - bpth = os.path.join(ws, name + ".cbc") + bpth = os.path.join(sim.simpath, sim.name + ".cbc") bobj = flopy.utils.CellBudgetFile(bpth, precision="double") bobj.get_unique_record_names() # ' STO-SS' @@ -361,7 +341,7 @@ def eval_model(sim): gwet = gwetv.reshape((np.sum(nstp), 5, 10, 10)) # Also retrieve the binary UZET output - uzpth = os.path.join(ws, name + ".uzf.bud") + uzpth = os.path.join(sim.simpath, sim.name + ".uzf.bud") uzobj = flopy.utils.CellBudgetFile(uzpth, precision="double") uzobj.get_unique_record_names() # b' FLOW-JA-FACE', @@ -473,36 +453,9 @@ def eval_model(sim): print("Finished running checks") -# - No need to change any code below -@pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), -) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_model, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_model, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print("standalone run of {}".format(os.path.basename(__file__))) - - # run main routine - main() +@pytest.mark.slow +@pytest.mark.parametrize("name", ex) +def test_mf6model(name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, 0, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_model, idxsim=0), str(function_tmpdir)) diff --git a/autotest/test_gwf_drn_ddrn01.py b/autotest/test_gwf_drn_ddrn01.py index 11a7ec66fa3..c1a6073eb3e 100644 --- a/autotest/test_gwf_drn_ddrn01.py +++ b/autotest/test_gwf_drn_ddrn01.py @@ -1,44 +1,17 @@ import os +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import running_on_CI, testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig paktest = "drn" budtol = 1e-2 - ex = ["drn_ddrn01a", "drn_ddrn01b"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) ddir = "data" - newton = [False, True] -# run all examples on Travis -continuous_integration = [True for idx in range(len(exdirs))] - -# set replace_exe to None to use default executable -replace_exe = None - # static model data # spatial discretization nlay, nrow, ncol = 1, 1, 100 @@ -218,54 +191,14 @@ def drain_smoothing(xdiff, xrange, newton=False): return f -# - No need to change any code below - - @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # determine if running on CI infrastructure - is_CI = running_on_CI() - r_exe = None - if not is_CI: - if replace_exe is not None: - r_exe = replace_exe - - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - if is_CI and not continuous_integration[idx]: - return - test.run_mf6( - Simulation(dir, exfunc=eval_disch, exe_dict=r_exe, idxsim=idx) +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run( + TestConfig(name=name, exes=targets, exfunc=eval_disch, idxsim=idx), + str(function_tmpdir) ) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation( - dir, exfunc=eval_disch, exe_dict=replace_exe, idxsim=idx - ) - test.run_mf6(sim) - return - - -# use python testmf6_drn_ddrn01.py -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_drn_ddrn02.py b/autotest/test_gwf_drn_ddrn02.py index 1e1c61f9f01..49556698287 100644 --- a/autotest/test_gwf_drn_ddrn02.py +++ b/autotest/test_gwf_drn_ddrn02.py @@ -3,39 +3,13 @@ import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import running_on_CI, testing_framework -from simulation import Simulation +import flopy + +from harness import TestHarness, TestConfig paktest = "drn" budtol = 1e-2 - ex = ["drn_ddrn02a"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" - -# run all examples on Travis -continuous_integration = [True for idx in range(len(exdirs))] - -# set replace_exe to None to use default executable -replace_exe = None # static model data # spatial discretization @@ -198,57 +172,15 @@ def eval_disch(sim): sim.success = True print(" " + msg) - return - - -# - No need to change any code below - @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # determine if running on CI infrastructure - is_CI = running_on_CI() - r_exe = None - if not is_CI: - if replace_exe is not None: - r_exe = replace_exe - - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - if is_CI and not continuous_integration[idx]: - return - test.run_mf6( - Simulation(dir, exfunc=eval_disch, exe_dict=r_exe, idxsim=idx) +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run( + TestConfig(name=str(function_tmpdir), exes=targets, exfunc=eval_disch, idxsim=idx), + str(function_tmpdir) ) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation( - dir, exfunc=eval_disch, exe_dict=replace_exe, idxsim=idx - ) - test.run_mf6(sim) - return - - -# use python testmf6_drn_ddrn01.py -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_errors.py b/autotest/test_gwf_errors.py index fe688406f16..d991d75c782 100644 --- a/autotest/test_gwf_errors.py +++ b/autotest/test_gwf_errors.py @@ -6,38 +6,18 @@ """ -import os -import shutil import subprocess +import flopy import numpy as np import pytest - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -import targets -from framework import set_teardown_test - -mf6_exe = os.path.abspath(targets.target_dict["mf6"]) -testname = "gwf_errors" -testdir = os.path.join("temp", testname) -os.makedirs(testdir, exist_ok=True) -everything_was_successful = True - -teardown_test = set_teardown_test() +from flopy.utils.gridutil import get_disu_kwargs def run_mf6(argv, ws): buff = [] proc = subprocess.Popen( - argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=ws - ) + argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=ws) result, error = proc.communicate() if result is not None: c = result.decode("utf-8") @@ -48,11 +28,9 @@ def run_mf6(argv, ws): return proc.returncode, buff -def run_mf6_error(ws, err_str_list): - returncode, buff = run_mf6([mf6_exe], ws) +def run_mf6_error(ws, exe, err_str_list): + returncode, buff = run_mf6([exe], ws) msg = "mf terminated with error" - if teardown_test: - shutil.rmtree(ws, ignore_errors=True) if returncode != 0: if not isinstance(err_str_list, list): err_str_list = list(err_str_list) @@ -68,6 +46,7 @@ def run_mf6_error(ws, err_str_list): def get_minimal_gwf_simulation( ws, + exe, name="test", simkwargs=None, simnamefilekwargs=None, @@ -111,7 +90,7 @@ def get_minimal_gwf_simulation( 0: [[(0, 0, 0), 0], [(0, nr - 1, nc - 1), 1]] } sim = flopy.mf6.MFSimulation( - sim_name=name, version="mf6", exe_name=mf6_exe, sim_ws=ws, **simkwargs + sim_name=name, version="mf6", exe_name=exe, sim_ws=ws, **simkwargs ) if simnamefilekwargs is not None: for k in simnamefilekwargs: @@ -129,47 +108,48 @@ def get_minimal_gwf_simulation( return sim -def test_simple_model_success(): +def test_simple_model_success(function_tmpdir, targets): + mf6 = targets.mf6 + # test a simple model to make sure it runs and terminates correctly - ws = f"{testdir}_sim0" - sim = get_minimal_gwf_simulation(ws) + sim = get_minimal_gwf_simulation(str(function_tmpdir), mf6) sim.write_simulation() - returncode, buff = run_mf6([mf6_exe], ws) + returncode, buff = run_mf6([mf6], str(function_tmpdir)) assert returncode == 0, "mf6 failed for simple model." final_message = "Normal termination of simulation." failure_message = f'mf6 did not terminate with "{final_message}"' assert final_message in buff[-1], failure_message - if teardown_test: - shutil.rmtree(ws, ignore_errors=True) - return -def test_empty_folder(): +def test_empty_folder(function_tmpdir, targets): + mf6 = targets.mf6 with pytest.raises(RuntimeError): # make sure mf6 fails when there is no simulation name file err_str = "mf6: mfsim.nam is not present in working directory." - run_mf6_error(testdir, err_str) + run_mf6_error(str(function_tmpdir), mf6, err_str) + +def test_sim_errors(function_tmpdir, targets): + mf6 = targets.mf6 -def test_sim_errors(): with pytest.raises(RuntimeError): # verify that the correct number of errors are reported - ws = f"{testdir}_sim1" chdkwargs = {} chdkwargs["stress_period_data"] = { 0: [[(0, 0, 0), 0.0] for i in range(10)] } - sim = get_minimal_gwf_simulation(ws, chdkwargs=chdkwargs) + sim = get_minimal_gwf_simulation(str(function_tmpdir), exe=mf6, chdkwargs=chdkwargs) sim.write_simulation() err_str = ["1. Cell is already a constant head ((1,1,1))."] - run_mf6_error(ws, err_str) + run_mf6_error(str(function_tmpdir), mf6, err_str) -def test_sim_maxerrors(): +def test_sim_maxerrors(function_tmpdir, targets): + mf6 = targets.mf6 + with pytest.raises(RuntimeError): # verify that the maxerrors keyword gives the correct error output - ws = f"{testdir}_sim2" simnamefilekwargs = {} simnamefilekwargs["maxerrors"] = 5 chdkwargs = {} @@ -177,7 +157,7 @@ def test_sim_maxerrors(): 0: [[(0, 0, 0), 0.0] for i in range(10)] } sim = get_minimal_gwf_simulation( - ws, simnamefilekwargs=simnamefilekwargs, chdkwargs=chdkwargs + str(function_tmpdir), exe=mf6, simnamefilekwargs=simnamefilekwargs, chdkwargs=chdkwargs ) sim.write_simulation() err_str = [ @@ -186,14 +166,13 @@ def test_sim_maxerrors(): "UNIT ERROR REPORT:", "1. ERROR OCCURRED WHILE READING FILE 'test.chd'", ] - run_mf6_error(ws, err_str) + run_mf6_error(str(function_tmpdir), mf6, err_str) -def test_disu_errors(): - with pytest.raises(RuntimeError): - from disu_util import get_disu_kwargs +def test_disu_errors(function_tmpdir, targets): + mf6 = targets.mf6 - ws = f"{testdir}_sim3" + with pytest.raises(RuntimeError): disukwargs = get_disu_kwargs( 3, 3, 3, np.ones(3), np.ones(3), 0, [-1, -2, -3] ) @@ -202,7 +181,7 @@ def test_disu_errors(): top[9] = 2.0 bot[9] = 1.0 sim = get_minimal_gwf_simulation( - ws, disukwargs=disukwargs, chdkwargs={"stress_period_data": [[]]} + str(function_tmpdir), exe=mf6, disukwargs=disukwargs, chdkwargs={"stress_period_data": [[]]} ) sim.write_simulation() err_str = [ @@ -212,34 +191,36 @@ def test_disu_errors(): "UNIT ERROR REPORT:" "1. ERROR OCCURRED WHILE READING FILE './test.disu'", ] - run_mf6_error(ws, err_str) + run_mf6_error(str(function_tmpdir), mf6, err_str) + +def test_solver_fail(function_tmpdir, targets): + mf6 = targets.mf6 -def test_solver_fail(): with pytest.raises(RuntimeError): # test failed to converge - ws = f"{testdir}_sim4" imskwargs = {"inner_maximum": 1, "outer_maximum": 2} - sim = get_minimal_gwf_simulation(ws, imskwargs=imskwargs) + sim = get_minimal_gwf_simulation(str(function_tmpdir), exe=mf6, imskwargs=imskwargs) sim.write_simulation() err_str = [ "Simulation convergence failure occurred 1 time(s).", "Premature termination of simulation.", ] - run_mf6_error(ws, err_str) + run_mf6_error(str(function_tmpdir), mf6, err_str) -def test_fail_continue_success(): +def test_fail_continue_success(function_tmpdir, targets): + mf6 = targets.mf6 + # test continue but failed to converge - ws = f"{testdir}_sim5" tdiskwargs = {"nper": 1, "perioddata": [(10.0, 10, 1.0)]} imskwargs = {"inner_maximum": 1, "outer_maximum": 2} sim = get_minimal_gwf_simulation( - ws, imskwargs=imskwargs, tdiskwargs=tdiskwargs + str(function_tmpdir), exe=mf6, imskwargs=imskwargs, tdiskwargs=tdiskwargs ) sim.name_file.continue_ = True sim.write_simulation() - returncode, buff = run_mf6([mf6_exe], ws) + returncode, buff = run_mf6([mf6], str(function_tmpdir)) assert returncode == 0, "mf6 failed for simple model." final_message = "Simulation convergence failure occurred 10 time(s)." @@ -249,21 +230,3 @@ def test_fail_continue_success(): final_message = "Normal termination of simulation." failure_message = f'mf6 did not terminate with "{final_message}"' assert final_message in buff[0], failure_message - - if teardown_test: - shutil.rmtree(ws, ignore_errors=True) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - test_empty_folder() - test_simple_model_success() - test_sim_errors() - test_sim_maxerrors() - test_disu_errors() - test_solver_fail() - test_fail_continue_success() diff --git a/autotest/test_gwf_evt01.py b/autotest/test_gwf_evt01.py index 0c435b49146..ae157a29b0c 100644 --- a/autotest/test_gwf_evt01.py +++ b/autotest/test_gwf_evt01.py @@ -1,32 +1,13 @@ import os -import sys import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +import flopy + +from harness import TestHarness, TestConfig ex = ["evt01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) def build_model(idx, dir): @@ -196,39 +177,12 @@ def eval_model(sim): msg = f"{kper} {h} {sim_evt_rate} {cal_evt_rate}" assert np.allclose(sim_evt_rate, cal_evt_rate), msg - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_model, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_model, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_model, idxsim=idx), str(function_tmpdir)) diff --git a/autotest/test_gwf_evt02.py b/autotest/test_gwf_evt02.py index 65d013c5e4c..58f518db4ac 100644 --- a/autotest/test_gwf_evt02.py +++ b/autotest/test_gwf_evt02.py @@ -1,35 +1,16 @@ import os -import sys import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +import flopy + +from harness import TestHarness, TestConfig ex = ["evt02"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -def build_model(idx, dir): +def build_model(idx, dir, exe): nlay, nrow, ncol = 1, 1, 3 chdheads = list(np.linspace(1, 100)) @@ -53,7 +34,7 @@ def build_model(idx, dir): # build MODFLOW 6 files ws = dir sim = flopy.mf6.MFSimulation( - sim_name=name, version="mf6", exe_name="mf6", sim_ws=ws + sim_name=name, version="mf6", exe_name=exe, sim_ws=ws ) # create tdis package tdis = flopy.mf6.ModflowTdis( @@ -178,39 +159,13 @@ def eval_model(sim): fpth = os.path.join(sim.simpath, "evt02.cbc") assert os.path.isfile(fpth), "model did not run with nseg=1 in EVT input" - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_model, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_model, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + mf6 = targets["mf6"] + test.build(lambda i, w: build_model(i, w, mf6), idx, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_model, idxsim=idx), str(function_tmpdir)) diff --git a/autotest/test_gwf_henry_nr.py b/autotest/test_gwf_henry_nr.py index ec9ffaacbe2..518af60bf38 100644 --- a/autotest/test_gwf_henry_nr.py +++ b/autotest/test_gwf_henry_nr.py @@ -5,27 +5,14 @@ # and DRNs alternate and move up and down along the boundary to represent # the effects of tides on the aquifer. -import os - +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation -from targets import get_mf6_version +from conftest import should_compare +from harness import TestHarness, TestConfig ex = ["gwf_henrynr01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) # global model variables nlay = 20 @@ -78,8 +65,7 @@ def sinfunc(a, b, c, d, x): return a * np.sin(b * (x - c)) + d -def build_model(idx, dir): - +def build_model(idx, dir, exe): ws = dir name = ex[idx] @@ -103,7 +89,7 @@ def build_model(idx, dir): # build MODFLOW 6 files sim = flopy.mf6.MFSimulation( - sim_name=name, version="mf6", exe_name="mf6", sim_ws=ws + sim_name=name, version="mf6", exe_name=exe, sim_ws=ws ) sim.name_file.continue_ = False @@ -245,64 +231,25 @@ def build_model(idx, dir): return sim, None -def set_make_comparison(): - version = get_mf6_version() - print(f"MODFLOW version='{version}'") - version = get_mf6_version(version="mf6-regression") - print(f"MODFLOW regression version='{version}'") - if version in ("6.2.1",): - make_comparison = False - else: - make_comparison = True - return make_comparison - - -# - No need to change any code below +@pytest.mark.slow @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6( - Simulation( - dir, +def test_mf6model(idx, name, function_tmpdir, targets): + name = "gwf-henry-nr" + comparisons = {name: ("6.2.1",)} + mf6 = targets["mf6"] + test = TestHarness() + test.build(lambda i, w: build_model(i, w, mf6), idx, str(function_tmpdir)) + test.run( + TestConfig( + name=name, + exes=targets, idxsim=idx, mf6_regression=True, cmp_verbose=False, - make_comparison=set_make_comparison(), - ) + make_comparison=should_compare(name, comparisons, targets), + ), + str(function_tmpdir) ) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, on_dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation( - on_dir, - idxsim=idx, - mf6_regression=True, - cmp_verbose=True, - make_comparison=set_make_comparison(), - ) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_ifmod_buy.py b/autotest/test_gwf_ifmod_buy.py index 65aad010cd6..598e1723878 100644 --- a/autotest/test_gwf_ifmod_buy.py +++ b/autotest/test_gwf_ifmod_buy.py @@ -3,16 +3,9 @@ import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) +import flopy -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig # General test for the interface model approach. # It compares the result of a single reference model @@ -37,9 +30,6 @@ # for convenience. Finally, the budget error is checked. ex = ["ifmod_buy01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) # some global convenience...: # model names @@ -655,42 +645,12 @@ def compare_to_ref(sim): cumul_balance_error, mname ) - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, exdir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -@pytest.mark.developmode -def test_mf6model(idx, exdir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, exdir) - - # run the test model - test.run_mf6(Simulation(exdir, exfunc=compare_to_ref, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test models - for idx, exdir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, exdir) - - sim = Simulation(exdir, exfunc=compare_to_ref, idxsim=idx) - test.run_mf6(sim) - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, exfunc=compare_to_ref, idxsim=idx), str(function_tmpdir)) diff --git a/autotest/test_gwf_ifmod_mult_exg.py b/autotest/test_gwf_ifmod_mult_exg.py index c4740a8157d..859fb14a0ed 100644 --- a/autotest/test_gwf_ifmod_mult_exg.py +++ b/autotest/test_gwf_ifmod_mult_exg.py @@ -26,24 +26,12 @@ import numpy as np import pytest from flopy.utils.lgrutil import Lgr -from modflowapi import ModflowApi -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) +import flopy -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["ifmod_mult_exg"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) - name_parent = "parent" name_child = "child" g_delr = 10.0 @@ -275,8 +263,6 @@ def build_model(idx, exdir): def eval_heads(sim): - name = ex[sim.idxsim] - fpth = os.path.join(sim.simpath, f"{name_parent}.hds") hds = flopy.utils.HeadFile(fpth) heads = hds.get_data() @@ -344,42 +330,12 @@ def exact(x): # assert maxdiff_child_south > maxdiff_child_north - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, exdir", - list(enumerate(exdirs)), + "name", + ex, ) -@pytest.mark.developmode -def test_mf6model(idx, exdir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, exdir) - - # run the test model - test.run_mf6(Simulation(exdir, exfunc=eval_heads, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test models - for idx, exdir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, exdir) - - sim = Simulation(exdir, exfunc=eval_heads, idxsim=idx) - test.run_mf6(sim) - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, 0, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_heads, idxsim=0), str(function_tmpdir)) diff --git a/autotest/test_gwf_ifmod_rewet.py b/autotest/test_gwf_ifmod_rewet.py index c51e816e4af..28aea67a761 100644 --- a/autotest/test_gwf_ifmod_rewet.py +++ b/autotest/test_gwf_ifmod_rewet.py @@ -3,16 +3,9 @@ import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) +import flopy -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig # General test for the interface model approach. # It compares the result of a single reference model @@ -39,9 +32,6 @@ # solution for convenience. Finally, the budget error is checked. ex = ["ifmod_rewet01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) # some global convenience...: # model names @@ -399,42 +389,12 @@ def compare_to_ref(sim): cumul_balance_error, mname ) - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, exdir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -@pytest.mark.developmode -def test_mf6model(idx, exdir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, exdir) - - # run the test model - test.run_mf6(Simulation(exdir, exfunc=compare_to_ref, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test models - for idx, exdir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, exdir) - - sim = Simulation(exdir, exfunc=compare_to_ref, idxsim=idx) - test.run_mf6(sim) - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, exfunc=compare_to_ref, idxsim=idx), str(function_tmpdir)) diff --git a/autotest/test_gwf_ifmod_vert.py b/autotest/test_gwf_ifmod_vert.py index ac1e10f0673..4013bd5e7e8 100644 --- a/autotest/test_gwf_ifmod_vert.py +++ b/autotest/test_gwf_ifmod_vert.py @@ -35,23 +35,12 @@ import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - +import flopy from flopy.utils.lgrutil import Lgr -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["ifmod_vert"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) parent_name = "parent" child_name = "child" @@ -292,41 +281,12 @@ def eval_heads(sim): errmsg = f"min or max residual too large {res.min()} {res.max()}" assert np.allclose(res, 0.0, atol=1.0e-6), errmsg - return - @pytest.mark.parametrize( - "idx, exdir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -@pytest.mark.developmode -def test_mf6model(idx, exdir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, exdir) - - # run the test model - test.run_mf6(Simulation(exdir, exfunc=eval_heads, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test models - for idx, exdir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, exdir) - - sim = Simulation(exdir, exfunc=eval_heads, idxsim=idx) - test.run_mf6(sim) - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_heads, idxsim=idx), str(function_tmpdir)) diff --git a/autotest/test_gwf_ifmod_xt3d01.py b/autotest/test_gwf_ifmod_xt3d01.py index dbbd2d74349..98085898b63 100644 --- a/autotest/test_gwf_ifmod_xt3d01.py +++ b/autotest/test_gwf_ifmod_xt3d01.py @@ -3,18 +3,10 @@ import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - +import flopy from flopy.utils.lgrutil import Lgr -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig # Test for the interface model approach, when running # with a GWF-GWF exchange and XT3D applied on it. @@ -41,9 +33,6 @@ # confirm that there is no budget error. ex = ["ifmod_xt3d01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) # globally for convenience... useXT3D = True @@ -314,8 +303,6 @@ def qxqyqz(fname, nlay, nrow, ncol): def eval_heads(sim): print("comparing heads and spec. discharges to analytical result...") - name = ex[sim.idxsim] - fpth = os.path.join(sim.simpath, f"{parent_name}.hds") hds = flopy.utils.HeadFile(fpth) heads = hds.get_data() @@ -475,7 +462,7 @@ def exact(x): ), "exchange observations do not match parent exchange flows" assert np.allclose( obsvalues, -child_exchange_flows - ), "exchange observations do not match child exchange flows" + ), "exchange observations do not match chile exchange flows" # Read the lumped boundname observations values fpth = os.path.join(sim.simpath, "gwf_obs_boundnames.csv") @@ -487,41 +474,12 @@ def exact(x): obsvalues, [-50.0, 50.0, 0, 0.0] ), "boundname observations do not match expected results" - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, exdir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, exdir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, exdir) - - # run the test model - test.run_mf6(Simulation(exdir, exfunc=eval_heads, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test models - for idx, exdir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, exdir) - - sim = Simulation(exdir, exfunc=eval_heads, idxsim=idx) - test.run_mf6(sim) - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, 0, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_heads, idxsim=0), str(function_tmpdir)) diff --git a/autotest/test_gwf_ifmod_xt3d02.py b/autotest/test_gwf_ifmod_xt3d02.py index b1e9146fdec..eee03a3ca67 100644 --- a/autotest/test_gwf_ifmod_xt3d02.py +++ b/autotest/test_gwf_ifmod_xt3d02.py @@ -3,18 +3,9 @@ import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) +import flopy -from flopy.utils.lgrutil import Lgr - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig # Test for the interface model approach. # It compares the result of a single, strongly anisotropic model @@ -42,10 +33,6 @@ # should be identical. Finally, the budget error is checked. ex = ["ifmod_xt3d02"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) - # global convenience... mname_ref = "refmodel" mname_left = "leftmodel" @@ -423,41 +410,12 @@ def compare_to_ref(sim): cumul_balance_error, mname ) - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, exdir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, exdir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, exdir) - - # run the test model - test.run_mf6(Simulation(exdir, exfunc=compare_to_ref, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test models - for idx, exdir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, exdir) - - sim = Simulation(exdir, exfunc=compare_to_ref, idxsim=idx) - test.run_mf6(sim) - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, exfunc=compare_to_ref, idxsim=idx), str(function_tmpdir)) diff --git a/autotest/test_gwf_ims_rcm_reorder.py b/autotest/test_gwf_ims_rcm_reorder.py index c4eca177504..f34144988f4 100644 --- a/autotest/test_gwf_ims_rcm_reorder.py +++ b/autotest/test_gwf_ims_rcm_reorder.py @@ -1,26 +1,13 @@ import os import pytest +import flopy +from flopy.utils.compare import eval_bud_diff -from budget_file_compare import eval_bud_diff - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig paktest = "ims" - -ex = [ - "ims_rcm", -] -exdirs = [os.path.join("temp", s) for s in ex] +ex = ["ims_rcm"] # spatial discretization data nlay, nrow, ncol = 2, 5, 30 @@ -31,9 +18,8 @@ chd_left = 10.0 chd_right = 5.0 -# -def build_model(idx, ws): +def build_model(idx, ws): # static model data # temporal discretization nper = 1 @@ -135,20 +121,19 @@ def build_models(idx, base_ws): def eval_flows(sim): - idx = sim.idxsim - name = ex[idx] + name = sim.name print("evaluating flow results..." f"({name})") - fpth = os.path.join(exdirs[idx], f"{name}.dis.grb") + fpth = os.path.join(sim.simpath, f"{name}.dis.grb") ia = flopy.mf6.utils.MfGrdFile(fpth).ia - fpth = os.path.join(exdirs[idx], f"{name}.cbc") + fpth = os.path.join(sim.simpath, f"{name}.cbc") b0 = flopy.utils.CellBudgetFile(fpth, precision="double") - fpth = os.path.join(exdirs[idx], "mf6", f"{name}.cbc") + fpth = os.path.join(sim.simpath, "mf6", f"{name}.cbc") b1 = flopy.utils.CellBudgetFile(fpth, precision="double") - fpth = os.path.join(exdirs[idx], f"{name}.cbc.cmp.out") + fpth = os.path.join(sim.simpath, f"{name}.cbc.cmp.out") eval_bud_diff(fpth, b0, b1, ia=ia) # close the budget files @@ -156,48 +141,20 @@ def eval_flows(sim): b1.close() -# - No need to change any code below @pytest.mark.parametrize( - "idx, exdir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, exdir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_models, idx, exdir) - - # run the test models - test.run_mf6( - Simulation( - exdir, +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_models, 0, ws) + test.run( + TestConfig( + name=name, + exes=targets, exfunc=eval_flows, - idxsim=idx, - ) + idxsim=0, + ), + ws ) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test models - for idx, exdir in enumerate(exdirs): - test.build_mf6_models(build_models, idx, exdir) - - sim = Simulation( - exdir, - exfunc=eval_flows, - idxsim=idx, - ) - test.run_mf6(sim) - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_lakobs01.py b/autotest/test_gwf_lakobs01.py index 8ff09c449c9..5845f6f081b 100644 --- a/autotest/test_gwf_lakobs01.py +++ b/autotest/test_gwf_lakobs01.py @@ -12,25 +12,11 @@ import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) +import flopy -import targets -from framework import testing_framework -from simulation import Simulation - -mf6_exe = os.path.abspath(targets.target_dict["mf6"]) +from harness import TestHarness, TestConfig ex = "gwf_lakobs_01a" -exdir = os.path.join("temp", ex) - - -# store global gwf for subsequent plotting gwf = None @@ -42,7 +28,7 @@ def get_idomain(nlay, nrow, ncol, lakend): return idomain -def build_model(): +def build_model(dir, exe): lx = 300.0 lz = 45.0 nlay = 45 @@ -75,8 +61,8 @@ def build_model(): sim = flopy.mf6.MFSimulation( sim_name=name, version="mf6", - exe_name=mf6_exe, - sim_ws=exdir, + exe_name=exe, + sim_ws=dir, ) # create tdis package @@ -220,69 +206,14 @@ def build_model(): return sim -# - No need to change any code below -def test_mf6model(): - # initialize testing framework - test = testing_framework() - - # build the models - sim = build_model() - - # write model input - sim.write_simulation() - - # attempt to run model, should fail - sim.run_simulation() - - # ensure that the error msg is contained in the mfsim.lst file - f = open(os.path.join(exdir, "mfsim.lst"), "r") - lines = f.readlines() - error_count = 0 - expected_msg = False - for line in lines: - if "ID2 (iconn) is missing" in line: - expected_msg = True - error_count += 1 - - assert error_count == 1, ( - "error count = " + str(error_count) + "but should equal 1" - ) - - # fix the error and attempt to rerun model - orig_fl = os.path.join(exdir, ex + ".lak.obs") - new_fl = os.path.join(exdir, ex + ".lak.obs.new") - sr = open(orig_fl, "r") - sw = open(new_fl, "w") - - lines = sr.readlines() - error_free_line = " lak1 lak 1 1\n" - for line in lines: - if " lak " in line: - sw.write(error_free_line) - else: - sw.write(line) - - sr.close() - sw.close() - - # delete original and replace with corrected lab obs input - os.remove(orig_fl) - os.rename(new_fl, orig_fl) - - # rerun the model, should be no errors - sim.run_simulation() - - shutil.rmtree(exdir, ignore_errors=True) - - return +def test_mf6model(function_tmpdir, targets): + mf6 = targets["mf6"] - -def main(): # initialize testing framework - test = testing_framework() + test = TestHarness() # build the models - sim = build_model() + sim = build_model(str(function_tmpdir), mf6) # write model input sim.write_simulation() @@ -291,7 +222,7 @@ def main(): sim.run_simulation() # ensure that the error msg is contained in the mfsim.lst file - f = open(os.path.join(exdir, "mfsim.lst"), "r") + f = open(str(function_tmpdir / "mfsim.lst"), "r") lines = f.readlines() error_count = 0 expected_msg = False @@ -301,12 +232,12 @@ def main(): error_count += 1 assert error_count == 1, ( - "error count = " + str(error_count) + ", but should equal 1" + "error count = " + str(error_count) + "but should equal 1" ) # fix the error and attempt to rerun model - orig_fl = os.path.join(exdir, ex + ".lak.obs") - new_fl = os.path.join(exdir, ex + ".lak.obs.new") + orig_fl = str(function_tmpdir / (ex + ".lak.obs")) + new_fl = str(function_tmpdir / (ex + ".lak.obs.new")) sr = open(orig_fl, "r") sw = open(new_fl, "w") @@ -327,16 +258,3 @@ def main(): # rerun the model, should be no errors sim.run_simulation() - - # clean the working directory - shutil.rmtree(exdir, ignore_errors=True) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_libmf6_evt01.py b/autotest/test_gwf_libmf6_evt01.py index 7bf1f6349d0..5ef7c608893 100644 --- a/autotest/test_gwf_libmf6_evt01.py +++ b/autotest/test_gwf_libmf6_evt01.py @@ -7,33 +7,14 @@ import os +import flopy import numpy as np import pytest from modflowapi import ModflowApi -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation, api_return +from harness import TestHarness, TestConfig ex = ["libgwf_evt01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) # et variables et_max = 0.1 @@ -172,24 +153,22 @@ def head2et_wellrate(h): def api_func(exe, idx, model_ws=None): - success = False - name = ex[idx].upper() - if model_ws is None: - model_ws = "." + if model_ws is None: model_ws = "." + output_file_path = os.path.join(model_ws, "mfsim.stdout") try: mf6 = ModflowApi(exe, working_directory=model_ws) except Exception as e: print("Failed to load " + exe) print("with message: " + str(e)) - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # initialize the model try: mf6.initialize() except: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # time loop current_time = mf6.get_current_time() @@ -252,7 +231,8 @@ def api_func(exe, idx, model_ws=None): break if not has_converged: - return api_return(success, model_ws) + print("model did not converge") + return False, open(output_file_path).readlines() # finalize time step mf6.finalize_solve() @@ -263,50 +243,21 @@ def api_func(exe, idx, model_ws=None): # increment counter idx += 1 + # cleanup try: mf6.finalize() - success = True except: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() - # cleanup and return - return api_return(success, model_ws) + return True, open(output_file_path).readlines() -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, idxsim=idx, api_func=api_func)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, idxsim=idx, api_func=api_func) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, idxsim=idx, api_func=api_func), str(function_tmpdir)) diff --git a/autotest/test_gwf_libmf6_ghb01.py b/autotest/test_gwf_libmf6_ghb01.py index 6cb729387ee..39f7d240ff2 100644 --- a/autotest/test_gwf_libmf6_ghb01.py +++ b/autotest/test_gwf_libmf6_ghb01.py @@ -8,34 +8,14 @@ """ import os +import flopy import numpy as np import pytest from modflowapi import ModflowApi -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation, api_return +from harness import TestHarness, TestConfig ex = ["libgwf_ghb01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) - # temporal discretization nper = 10 @@ -203,24 +183,23 @@ def api_ghb_pak(hcof, rhs): def api_func(exe, idx, model_ws=None): - success = False - name = ex[idx].upper() if model_ws is None: model_ws = "." + output_file_path = os.path.join(model_ws, "mfsim.stdout") try: mf6 = ModflowApi(exe, working_directory=model_ws) except Exception as e: print("Failed to load " + exe) print("with message: " + str(e)) - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # initialize the model try: mf6.initialize() except: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # time loop current_time = mf6.get_current_time() @@ -291,47 +270,18 @@ def api_func(exe, idx, model_ws=None): # cleanup try: mf6.finalize() - success = True except: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # cleanup and return - return api_return(success, model_ws) + return True, open(output_file_path).readlines() -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, idxsim=idx, api_func=api_func)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, idxsim=idx, api_func=api_func) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, idxsim=idx, api_func=api_func), str(function_tmpdir)) diff --git a/autotest/test_gwf_libmf6_ifmod01.py b/autotest/test_gwf_libmf6_ifmod01.py index 3f138e5dc20..e6a9a580bc0 100644 --- a/autotest/test_gwf_libmf6_ifmod01.py +++ b/autotest/test_gwf_libmf6_ifmod01.py @@ -14,33 +14,13 @@ """ import os -import numpy as np +import flopy import pytest from modflowapi import ModflowApi -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation, api_return +from harness import TestHarness, TestConfig ex = ["libgwf_ifmod01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) # global convenience... name_left = "leftmodel" @@ -231,24 +211,22 @@ def build_model(idx, dir): def api_func(exe, idx, model_ws=None): - success = False - - name = ex[idx].upper() if model_ws is None: model_ws = "." + output_file_path = os.path.join(model_ws, "mfsim.stdout") try: mf6 = ModflowApi(exe, working_directory=model_ws) except Exception as e: print("Failed to load " + exe) print("with message: " + str(e)) - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # initialize the model try: mf6.initialize() except: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # test the interface models check_interface_models(mf6) @@ -260,18 +238,17 @@ def api_func(exe, idx, model_ws=None): try: mf6.update() except: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() current_time = mf6.get_current_time() # finish try: mf6.finalize() - success = True except: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # cleanup and return - return api_return(success, model_ws) + return True, open(output_file_path).readlines() def check_interface_models(mf6): @@ -330,38 +307,12 @@ def check_interface_models(mf6): ), "AREA in interface model does not match" -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, idxsim=idx, api_func=api_func)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test models - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, idxsim=idx, api_func=api_func) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, idxsim=idx, api_func=api_func), ws) diff --git a/autotest/test_gwf_libmf6_ifmod02.py b/autotest/test_gwf_libmf6_ifmod02.py index d0a1826f2cd..c8d59d8a86a 100644 --- a/autotest/test_gwf_libmf6_ifmod02.py +++ b/autotest/test_gwf_libmf6_ifmod02.py @@ -38,33 +38,14 @@ """ import os +import flopy import numpy as np import pytest from modflowapi import ModflowApi -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation, api_return +from harness import TestHarness, TestConfig ex = ["libgwf_ifmod02"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) # global convenience... name_tl = "topleft" @@ -324,24 +305,23 @@ def build_model(idx, dir): def api_func(exe, idx, model_ws=None): - success = False - - name = ex[idx].upper() if model_ws is None: model_ws = "." + output_file_path = os.path.join(model_ws, "mfsim.stdout") + try: mf6 = ModflowApi(exe, working_directory=model_ws) except Exception as e: print("Failed to load " + exe) print("with message: " + str(e)) - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # initialize the model try: mf6.initialize() except: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # test the interface models check_interface_models(mf6) @@ -353,18 +333,17 @@ def api_func(exe, idx, model_ws=None): try: mf6.update() except: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() current_time = mf6.get_current_time() # finish try: mf6.finalize() - success = True except: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # cleanup and return - return api_return(success, model_ws) + return True, open(output_file_path).readlines() def check_interface_models(mf6): @@ -424,39 +403,11 @@ def check_interface_models(mf6): ) -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -@pytest.mark.developmode -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, idxsim=idx, api_func=api_func)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test models - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, idxsim=idx, api_func=api_func) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, idxsim=idx, api_func=api_func), str(function_tmpdir)) diff --git a/autotest/test_gwf_libmf6_ifmod03.py b/autotest/test_gwf_libmf6_ifmod03.py index 003a03b2d8f..5d51cca43ea 100644 --- a/autotest/test_gwf_libmf6_ifmod03.py +++ b/autotest/test_gwf_libmf6_ifmod03.py @@ -28,33 +28,14 @@ """ import os +import flopy import numpy as np import pytest from modflowapi import ModflowApi -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation, api_return +from harness import TestHarness, TestConfig ex = ["libgwf_ifmod03"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) # global convenience... name_left = "left" @@ -241,24 +222,23 @@ def build_model(idx, dir): def api_func(exe, idx, model_ws=None): - success = False - - name = ex[idx].upper() if model_ws is None: model_ws = "." + output_file_path = os.path.join(model_ws, "mfsim.stdout") + try: mf6 = ModflowApi(exe, working_directory=model_ws) except Exception as e: print("Failed to load " + exe) print("with message: " + str(e)) - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # initialize the model try: mf6.initialize() except: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # test the interface models check_interface_models(mf6) @@ -270,7 +250,7 @@ def api_func(exe, idx, model_ws=None): try: mf6.update() except: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() current_time = mf6.get_current_time() # finish @@ -278,10 +258,10 @@ def api_func(exe, idx, model_ws=None): mf6.finalize() success = True except: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # cleanup and return - return api_return(success, model_ws) + return True, open(output_file_path).readlines() def check_interface_models(mf6): @@ -309,38 +289,11 @@ def check_interface_models(mf6): assert abs(ymax - ymin) < 1e-6 -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, idxsim=idx, api_func=api_func)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test models - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, idxsim=idx, api_func=api_func) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, idxsim=idx, api_func=api_func), str(function_tmpdir)) diff --git a/autotest/test_gwf_libmf6_rch01.py b/autotest/test_gwf_libmf6_rch01.py index 07592d15a94..239e64c18d8 100644 --- a/autotest/test_gwf_libmf6_rch01.py +++ b/autotest/test_gwf_libmf6_rch01.py @@ -10,33 +10,14 @@ import os +import flopy import numpy as np import pytest from modflowapi import ModflowApi -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation, api_return +from harness import TestHarness, TestConfig ex = ["libgwf_rch01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) # recharge package name rch_pname = "RCH-1" @@ -168,24 +149,24 @@ def build_model(idx, dir): def api_func(exe, idx, model_ws=None): - success = False - name = ex[idx].upper() if model_ws is None: model_ws = "." + output_file_path = os.path.join(model_ws, "mfsim.stdout") + try: mf6 = ModflowApi(exe, working_directory=model_ws) except Exception as e: print("Failed to load " + exe) print("with message: " + str(e)) - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # initialize the model try: mf6.initialize() except: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # time loop current_time = mf6.get_current_time() @@ -229,7 +210,7 @@ def api_func(exe, idx, model_ws=None): break if not has_converged: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # finalize time step mf6.finalize_solve() @@ -244,47 +225,18 @@ def api_func(exe, idx, model_ws=None): # cleanup try: mf6.finalize() - success = True except: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # cleanup and return - return api_return(success, model_ws) + return True, open(output_file_path).readlines() -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, idxsim=idx, api_func=api_func)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, idxsim=idx, api_func=api_func) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, idxsim=idx, api_func=api_func), str(function_tmpdir)) diff --git a/autotest/test_gwf_libmf6_rch02.py b/autotest/test_gwf_libmf6_rch02.py index 3ed421c2254..e283a6b814e 100644 --- a/autotest/test_gwf_libmf6_rch02.py +++ b/autotest/test_gwf_libmf6_rch02.py @@ -7,33 +7,14 @@ import os +import flopy import numpy as np import pytest from modflowapi import ModflowApi -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation, api_return +from harness import TestHarness, TestConfig ex = ["libgwf_rch02"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) # recharge package name rch_pname = "RCH-1" @@ -88,7 +69,7 @@ hclose, rclose, relax = 1e-9, 1e-3, 0.97 -def get_model(ws, name, rech=rch_spd): +def get_model(ws, name, exe, rech=rch_spd): sim = flopy.mf6.MFSimulation( sim_name=name, version="mf6", @@ -172,15 +153,15 @@ def get_model(ws, name, rech=rch_spd): return sim -def build_model(idx, dir): +def build_model(idx, dir, exe): # build MODFLOW 6 files ws = dir name = ex[idx] - sim = get_model(ws, name) + sim = get_model(ws, name, exe) # build comparison model ws = os.path.join(dir, "libmf6") - mc = get_model(ws, name, rech=0.0) + mc = get_model(ws, name, exe, rech=0.0) return sim, mc @@ -203,13 +184,14 @@ def run_perturbation(mf6, max_iter, recharge, tag, rch): def api_func(exe, idx, model_ws=None): print("\nBMI implementation test:") - success = False name = ex[idx].upper() init_wd = os.path.abspath(os.getcwd()) if model_ws is not None: os.chdir(model_ws) + output_file_path = os.path.join(model_ws, "mfsim.stdout") + # get the observations from the standard run fpth = os.path.join("..", f"{ex[idx]}.head.obs.csv") hobs = np.genfromtxt(fpth, delimiter=",", names=True)["H1_6_6"] @@ -219,13 +201,13 @@ def api_func(exe, idx, model_ws=None): except Exception as e: print("Failed to load " + exe) print("with message: " + str(e)) - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # initialize the model try: mf6.initialize() except: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # time loop current_time = mf6.get_current_time() @@ -265,7 +247,7 @@ def api_func(exe, idx, model_ws=None): mf6, max_iter, new_recharge, rch_tag, rch ) if not has_converged: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() h0 = head.reshape((nrow, ncol))[5, 5] r0 = h0 - htarget @@ -274,7 +256,7 @@ def api_func(exe, idx, model_ws=None): mf6, max_iter, new_recharge, rch_tag, rch + drch ) if not has_converged: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() h1 = head.reshape((nrow, ncol))[5, 5] r1 = h1 - htarget @@ -302,7 +284,7 @@ def api_func(exe, idx, model_ws=None): mf6, max_iter, new_recharge, rch_tag, rch ) if not has_converged: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # finalize time step mf6.finalize_solve() @@ -316,50 +298,21 @@ def api_func(exe, idx, model_ws=None): # cleanup try: mf6.finalize() - success = True except: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() if model_ws is not None: os.chdir(init_wd) # cleanup and return - return api_return(success, model_ws) + return True, open(output_file_path).readlines() -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, idxsim=idx, api_func=api_func)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, idxsim=idx, api_func=api_func) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(lambda i, d: build_model(i, d, targets["mf6"]), idx, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, idxsim=idx, api_func=api_func), str(function_tmpdir)) diff --git a/autotest/test_gwf_libmf6_riv01.py b/autotest/test_gwf_libmf6_riv01.py index 7a753137e86..e5fc7230df6 100644 --- a/autotest/test_gwf_libmf6_riv01.py +++ b/autotest/test_gwf_libmf6_riv01.py @@ -5,34 +5,14 @@ """ import os +import flopy import numpy as np import pytest from modflowapi import ModflowApi -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation, api_return +from harness import TestHarness, TestConfig ex = ["libgwf_riv01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) - # temporal discretization nper = 10 @@ -174,24 +154,24 @@ def build_model(idx, dir): def api_func(exe, idx, model_ws=None): - success = False - name = ex[idx].upper() if model_ws is None: model_ws = "." + output_file_path = os.path.join(model_ws, "mfsim.stdout") + try: mf6 = ModflowApi(exe, working_directory=model_ws) except Exception as e: print("Failed to load " + exe) print("with message: " + str(e)) - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # initialize the model try: mf6.initialize() except: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # time loop current_time = mf6.get_current_time() @@ -240,7 +220,7 @@ def api_func(exe, idx, model_ws=None): break if not has_converged: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # finalize time step mf6.finalize_solve() @@ -255,47 +235,18 @@ def api_func(exe, idx, model_ws=None): # cleanup try: mf6.finalize() - success = True except: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # cleanup and return - return api_return(success, model_ws) + return True, open(output_file_path).readlines() -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, idxsim=idx, api_func=api_func)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, idxsim=idx, api_func=api_func) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, idxsim=idx, api_func=api_func), str(function_tmpdir)) diff --git a/autotest/test_gwf_libmf6_riv02.py b/autotest/test_gwf_libmf6_riv02.py index 67d7f04fd20..3c63a337a5f 100644 --- a/autotest/test_gwf_libmf6_riv02.py +++ b/autotest/test_gwf_libmf6_riv02.py @@ -5,34 +5,14 @@ """ import os +import flopy import numpy as np import pytest from modflowapi import ModflowApi -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation, api_return +from harness import TestHarness, TestConfig ex = ["libgwf_riv02"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) - # temporal discretization nper = 10 @@ -188,24 +168,24 @@ def api_riv_pak(stage, h, hcof, rhs): def api_func(exe, idx, model_ws=None): - success = False - name = ex[idx].upper() if model_ws is None: model_ws = "." + output_file_path = os.path.join(model_ws, "mfsim.stdout") + try: mf6 = ModflowApi(exe, working_directory=model_ws) except Exception as e: print("Failed to load " + exe) print("with message: " + str(e)) - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # initialize the model try: mf6.initialize() except: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # time loop current_time = mf6.get_current_time() @@ -287,45 +267,17 @@ def api_func(exe, idx, model_ws=None): mf6.finalize() success = True except: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # cleanup and return - return api_return(success, model_ws) + return True, open(output_file_path).readlines() -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, idxsim=idx, api_func=api_func)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, idxsim=idx, api_func=api_func) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, idxsim=idx, api_func=api_func), str(function_tmpdir)) diff --git a/autotest/test_gwf_libmf6_sto01.py b/autotest/test_gwf_libmf6_sto01.py index 80e4365cd59..f18fcd84e6b 100644 --- a/autotest/test_gwf_libmf6_sto01.py +++ b/autotest/test_gwf_libmf6_sto01.py @@ -7,33 +7,14 @@ import os +import flopy import numpy as np import pytest from modflowapi import ModflowApi -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation, api_return +from harness import TestHarness, TestConfig ex = ["libgwf_sto01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) # average recharge rate avg_rch = 0.001 @@ -171,24 +152,24 @@ def build_model(idx, dir): def api_func(exe, idx, model_ws=None): - success = False - name = ex[idx].upper() if model_ws is None: model_ws = "." + output_file_path = os.path.join(model_ws, "mfsim.stdout") + try: mf6 = ModflowApi(exe, working_directory=model_ws) except Exception as e: print("Failed to load " + exe) print("with message: " + str(e)) - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # initialize the model try: mf6.initialize() except: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # time loop current_time = mf6.get_current_time() @@ -209,7 +190,7 @@ def api_func(exe, idx, model_ws=None): try: mf6.update() except: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # update time current_time = mf6.get_current_time() @@ -220,47 +201,19 @@ def api_func(exe, idx, model_ws=None): # cleanup try: mf6.finalize() - success = True except: - return api_return(success, model_ws) + return False, open(output_file_path).readlines() # cleanup and return - return api_return(success, model_ws) + return True, open(output_file_path).readlines() -# - No need to change any code below +@pytest.mark.slow @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, idxsim=idx, api_func=api_func)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, idxsim=idx, api_func=api_func) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets, idxsim=idx, api_func=api_func), str(function_tmpdir)) diff --git a/autotest/test_gwf_maw01.py b/autotest/test_gwf_maw01.py deleted file mode 100644 index 425388bf22f..00000000000 --- a/autotest/test_gwf_maw01.py +++ /dev/null @@ -1,252 +0,0 @@ -import os - -import numpy as np -import pytest - -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation - -ex = ["maw01", "maw01nwt", "maw01nwtur"] -newtonoptions = [None, "NEWTON", "NEWTON UNDER_RELAXATION"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" - - -def build_model(idx, dir): - - nlay, nrow, ncol = 1, 1, 3 - nper = 3 - perlen = [1.0, 1.0, 1.0] - nstp = [1, 1, 1] - tsmult = [1.0, 1.0, 1.0] - lenx = 300.0 - delr = delc = lenx / float(nrow) - strt = 100.0 - hnoflo = 1e30 - hdry = -1e30 - hk = 1.0 - - nouter, ninner = 100, 300 - hclose, rclose, relax = 1e-9, 1e-3, 1.0 - krylov = ["CG", "BICGSTAB", "BICGSTAB"] - - tdis_rc = [] - for i in range(nper): - tdis_rc.append((perlen[i], nstp[i], tsmult[i])) - - name = ex[idx] - - # build MODFLOW 6 files - ws = dir - sim = flopy.mf6.MFSimulation( - sim_name=name, version="mf6", exe_name="mf6", sim_ws=ws - ) - # create tdis package - tdis = flopy.mf6.ModflowTdis( - sim, time_units="DAYS", nper=nper, perioddata=tdis_rc - ) - - # create gwf model - gwf = flopy.mf6.MFModel( - sim, - model_type="gwf6", - modelname=name, - model_nam_file=f"{name}.nam", - ) - gwf.name_file.newtonoptions = newtonoptions[idx] - - # create iterative model solution and register the gwf model with it - ims = flopy.mf6.ModflowIms( - sim, - print_option="SUMMARY", - outer_dvclose=hclose, - outer_maximum=nouter, - under_relaxation="NONE", - inner_maximum=ninner, - inner_dvclose=hclose, - rcloserecord=rclose, - linear_acceleration=krylov[idx], - scaling_method="NONE", - reordering_method="NONE", - relaxation_factor=relax, - ) - sim.register_ims_package(ims, [gwf.name]) - - dis = flopy.mf6.ModflowGwfdis( - gwf, - nlay=nlay, - nrow=nrow, - ncol=ncol, - delr=delr, - delc=delc, - top=100.0, - botm=0.0, - idomain=1, - filename=f"{name}.dis", - ) - - # initial conditions - ic = flopy.mf6.ModflowGwfic(gwf, strt=strt, filename=f"{name}.ic") - - # node property flow - npf = flopy.mf6.ModflowGwfnpf( - gwf, - save_flows=True, - icelltype=1, - k=hk, - k33=hk, - filename=f"{name}.npf", - ) - # storage - sto = flopy.mf6.ModflowGwfsto( - gwf, - save_flows=True, - iconvert=1, - ss=0.0, - sy=0.1, - steady_state={0: True}, - # transient={1: False}, - filename=f"{name}.sto", - ) - - # chd files - chdlist0 = [] - chdlist0.append([(0, 0, 0), 100.0]) - chdlist0.append([(0, 0, 2), 100.0]) - - chdlist1 = [] - chdlist1.append([(0, 0, 0), 25.0]) - chdlist1.append([(0, 0, 2), 25.0]) - - chdspdict = {0: chdlist0, 1: chdlist1, 2: chdlist0} - chd = flopy.mf6.ModflowGwfchd( - gwf, - stress_period_data=chdspdict, - save_flows=False, - filename=f"{name}.chd", - ) - - # wel files - # wel = flopy.mf6.ModflowGwfwel(gwf, print_input=True, print_flows=True, - # maxbound=len(ws), - # periodrecarray=wd6, - # save_flows=False) - # MAW - opth = f"{name}.maw.obs" - wellbottom = 50.0 - wellrecarray = [[0, 0.1, wellbottom, 100.0, "THIEM", 1]] - wellconnectionsrecarray = [[0, 0, (0, 0, 1), 100.0, wellbottom, 1.0, 0.1]] - wellperiodrecarray = [[0, "rate", 0.0]] - mawo_dict = {} - mawo_dict["maw_obs.csv"] = [("mh1", "head", 1)] - maw = flopy.mf6.ModflowGwfmaw( - gwf, - filename=f"{name}.maw", - print_input=True, - print_head=True, - print_flows=True, - save_flows=True, - observations=mawo_dict, - packagedata=wellrecarray, - connectiondata=wellconnectionsrecarray, - perioddata=wellperiodrecarray, - ) - - # output control - oc = flopy.mf6.ModflowGwfoc( - gwf, - budget_filerecord=f"{name}.cbc", - head_filerecord=f"{name}.hds", - headprintrecord=[("COLUMNS", 10, "WIDTH", 15, "DIGITS", 6, "GENERAL")], - saverecord=[("HEAD", "ALL")], - printrecord=[("HEAD", "ALL"), ("BUDGET", "ALL")], - filename=f"{name}.oc", - ) - - return sim, None - - -def eval_maw(sim): - print("evaluating MAW heads...") - - # MODFLOW 6 maw results - fpth = os.path.join(sim.simpath, "maw_obs.csv") - try: - tc = np.genfromtxt(fpth, names=True, delimiter=",") - except: - assert False, f'could not load data from "{fpth}"' - - # create known results array - tc0 = np.array([100.0, 25.0, 100.0]) - - # calculate maximum absolute error - diff = tc["MH1"] - tc0 - diffmax = np.abs(diff).max() - dtol = 1e-9 - msg = f"maximum absolute maw head difference ({diffmax}) " - - if diffmax > dtol: - sim.success = False - msg += f"exceeds {dtol}" - assert diffmax < dtol, msg - else: - sim.success = True - print(" " + msg) - - return - - -# - No need to change any code below -@pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), -) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_maw, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_maw, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_maw02.py b/autotest/test_gwf_maw02.py deleted file mode 100644 index 745264a71cd..00000000000 --- a/autotest/test_gwf_maw02.py +++ /dev/null @@ -1,357 +0,0 @@ -import os -import sys - -import numpy as np -import pytest - -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation - -ex = ["maw02"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" - -budtol = 1e-2 -bud_lst = ["GWF_IN", "GWF_OUT", "RATE_IN", "RATE_OUT"] - -# spatial and temporal data -nlay, nrow, ncol = 1, 1, 3 -shape3d = (nlay, nrow, ncol) -size3d = nlay * nrow * ncol -nper = 5 -perlen = nper * [1.0] -nstp = nper * [1] -tsmult = nper * [1.0] -steady = nper * [True] -lenx = 300.0 -delr = delc = lenx / float(nrow) -botm = [0.0] -strt = 100.0 -hnoflo = 1e30 -hdry = -1e30 -hk = 1.0 - -nouter, ninner = 100, 300 -hclose, rclose, relax = 1e-9, 1e-3, 1.0 -krylov = ["CG"] - -tdis_rc = [] -for i in range(nper): - tdis_rc.append((perlen[i], nstp[i], tsmult[i])) - - -def build_model(idx, dir): - - name = ex[idx] - - # build MODFLOW 6 files - ws = dir - sim = flopy.mf6.MFSimulation( - sim_name=name, version="mf6", exe_name="mf6", sim_ws=ws - ) - # create tdis package - tdis = flopy.mf6.ModflowTdis( - sim, time_units="DAYS", nper=nper, perioddata=tdis_rc - ) - - # create gwf model - gwf = flopy.mf6.MFModel( - sim, - model_type="gwf6", - modelname=name, - model_nam_file=f"{name}.nam", - ) - - # create iterative model solution and register the gwf model with it - ims = flopy.mf6.ModflowIms( - sim, - print_option="SUMMARY", - outer_dvclose=hclose, - outer_maximum=nouter, - under_relaxation="NONE", - inner_maximum=ninner, - inner_dvclose=hclose, - rcloserecord=rclose, - linear_acceleration=krylov[idx], - scaling_method="NONE", - reordering_method="NONE", - relaxation_factor=relax, - ) - sim.register_ims_package(ims, [gwf.name]) - - dis = flopy.mf6.ModflowGwfdis( - gwf, - nlay=nlay, - nrow=nrow, - ncol=ncol, - delr=delr, - delc=delc, - top=100.0, - botm=0.0, - idomain=1, - filename=f"{name}.dis", - ) - - # initial conditions - ic = flopy.mf6.ModflowGwfic(gwf, strt=strt, filename=f"{name}.ic") - - # node property flow - npf = flopy.mf6.ModflowGwfnpf( - gwf, - save_flows=True, - icelltype=1, - k=hk, - k33=hk, - filename=f"{name}.npf", - ) - # storage - sto = flopy.mf6.ModflowGwfsto( - gwf, - save_flows=True, - iconvert=1, - ss=0.0, - sy=0.1, - steady_state={0: True}, - # transient={1: False}, - filename=f"{name}.sto", - ) - - # chd files - chdlist0 = [] - chdlist0.append([(0, 0, 0), 100.0]) - chdlist0.append([(0, 0, 2), 100.0]) - - chdlist1 = [] - chdlist1.append([(0, 0, 0), 25.0]) - chdlist1.append([(0, 0, 2), 25.0]) - - chdspdict = {0: chdlist0, 1: chdlist1, 2: chdlist0} - chd = flopy.mf6.ModflowGwfchd( - gwf, - stress_period_data=chdspdict, - save_flows=False, - filename=f"{name}.chd", - ) - - # MAW - opth = f"{name}.maw.obs" - wellbottom = 0.0 - wellrecarray = [ - [0, 0.1, wellbottom, 100.0, "THIEM", 1], - [1, 0.1, wellbottom, 100.0, "THIEM", 1], - ] - wellconnectionsrecarray = [ - [0, 0, (0, 0, 1), 100.0, wellbottom, 1.0, 0.1], - [1, 0, (0, 0, 1), 100.0, wellbottom, 1.0, 0.1], - ] - wellperiodrecarray = { - 0: [ - [0, "rate", -20.0], - [0, "status", "inactive"], - [0, "rate_scaling", 1.0, 15.0], - [1, "rate", -30.0], - [1, "status", "inactive"], - [1, "rate_scaling", 5.0, 15.0], - ], - 1: [ - [0, "rate", -110.0], - [0, "status", "active"], - [1, "rate", -130.0], - [1, "status", "active"], - ], - 3: [[0, "status", "inactive"]], - 4: [[0, "status", "active"]], - } - mawo_dict = {} - mawo_dict["maw_obs.csv"] = [("mh1", "head", 1)] - maw = flopy.mf6.ModflowGwfmaw( - gwf, - filename=f"{name}.maw", - budget_filerecord=f"{name}.maw.cbc", - print_input=True, - print_head=True, - print_flows=True, - save_flows=True, - observations=mawo_dict, - packagedata=wellrecarray, - connectiondata=wellconnectionsrecarray, - perioddata=wellperiodrecarray, - pname="MAW-1", - ) - - # output control - oc = flopy.mf6.ModflowGwfoc( - gwf, - budget_filerecord=f"{name}.cbc", - head_filerecord=f"{name}.hds", - headprintrecord=[("COLUMNS", 10, "WIDTH", 15, "DIGITS", 6, "GENERAL")], - saverecord=[("HEAD", "ALL"), ("BUDGET", "ALL")], - printrecord=[("HEAD", "ALL"), ("BUDGET", "ALL")], - filename=f"{name}.oc", - ) - - return sim, None - - -def eval_maw(sim): - print("evaluating MAW budgets...") - - # get results from listing file - fpth = os.path.join(sim.simpath, f"{os.path.basename(sim.name)}.lst") - budl = flopy.utils.Mf6ListBudget( - fpth, budgetkey="MAW-1 BUDGET FOR ENTIRE MODEL AT END OF TIME STEP" - ) - names = list(bud_lst) - d0 = budl.get_budget(names=names)[0] - dtype = d0.dtype - nbud = d0.shape[0] - - # get results from cbc file - cbc_bud = ["GWF", "RATE"] - d = np.recarray(nbud, dtype=dtype) - for key in bud_lst: - d[key] = 0.0 - fpth = os.path.join(sim.simpath, f"{os.path.basename(sim.name)}.maw.cbc") - cobj = flopy.utils.CellBudgetFile(fpth, precision="double") - kk = cobj.get_kstpkper() - times = cobj.get_times() - cbc_vals = [] - for idx, (k, t) in enumerate(zip(kk, times)): - for text in cbc_bud: - qin = 0.0 - qout = 0.0 - v = cobj.get_data(kstpkper=k, text=text)[0] - if isinstance(v, np.recarray): - vt = np.zeros(size3d, dtype=float) - wq = [] - for jdx, node in enumerate(v["node"]): - vt[node - 1] += v["q"][jdx] - wq.append(v["q"][jdx]) - v = vt.reshape(shape3d) - if text == cbc_bud[-1]: - cbc_vals.append(wq) - for kk in range(v.shape[0]): - for ii in range(v.shape[1]): - for jj in range(v.shape[2]): - vv = v[kk, ii, jj] - if vv < 0.0: - qout -= vv - else: - qin += vv - d["totim"][idx] = t - d["time_step"][idx] = k[0] - d["stress_period"] = k[1] - key = f"{text}_IN" - d[key][idx] = qin - key = f"{text}_OUT" - d[key][idx] = qout - - maw_vals = [ - [0.000, 0.000], - [-106.11303563809453, -96.22598985147631], - [-110.000, -130.000], - [0.0, -130.000], - [-110.000, -130.000], - ] - - # evaluate if well rates in cbc file are equal to expected values - diffv = [] - for ovs, svs in zip(maw_vals, cbc_vals): - for ov, sv in zip(ovs, svs): - diffv.append(ov - sv) - diffv = np.abs(np.array(diffv)).max() - msg = f"\nmaximum absolute maw rate difference ({diffv})\n" - - # calculate difference between water budget items in the lst and cbc files - diff = np.zeros((nbud, len(bud_lst)), dtype=float) - for idx, key in enumerate(bud_lst): - diff[:, idx] = d0[key] - d[key] - diffmax = np.abs(diff).max() - msg += f"maximum absolute total-budget difference ({diffmax}) " - - # write summary - fpth = os.path.join( - sim.simpath, f"{os.path.basename(sim.name)}.bud.cmp.out" - ) - f = open(fpth, "w") - for i in range(diff.shape[0]): - if i == 0: - line = f"{'TIME':>10s}" - for idx, key in enumerate(bud_lst): - line += f"{key + '_LST':>25s}" - line += f"{key + '_CBC':>25s}" - line += f"{key + '_DIF':>25s}" - f.write(line + "\n") - line = f"{d['totim'][i]:10g}" - for idx, key in enumerate(bud_lst): - line += f"{d0[key][i]:25g}" - line += f"{d[key][i]:25g}" - line += f"{diff[i, idx]:25g}" - f.write(line + "\n") - f.close() - - if diffmax > budtol or diffv > budtol: - sim.success = False - msg += f"\n...exceeds {budtol}" - assert diffmax < budtol, msg - else: - sim.success = True - print(" " + msg) - - return - - -# - No need to change any code below -@pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), -) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_maw, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_maw, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_maw03.py b/autotest/test_gwf_maw03.py deleted file mode 100644 index 0ef3963d939..00000000000 --- a/autotest/test_gwf_maw03.py +++ /dev/null @@ -1,275 +0,0 @@ -""" -MODFLOW 6 Autotest -Test the MAW HEAD_LIMIT and RATE_SCALING options for injection wells. These -options were not originally supported in MODFLOW 6. They were added for -version 6.0.4. - -""" - -import os -import sys - -import numpy as np -import pytest - -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation - -ex = ["maw03a", "maw03b", "maw03c"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) - -# maw settings for runs a, b, and c -mawsetting_a = [ - (0, "rate", 2000.0), -] -mawsetting_b = [(0, "rate", 2000.0), (0, "head_limit", 0.4)] -mawsetting_c = [(0, "rate", 2000.0), (0, "rate_scaling", 0.0, 1.0)] -mawsettings = [mawsetting_a, mawsetting_b, mawsetting_c] - - -def build_model(idx, dir): - - nlay, nrow, ncol = 1, 101, 101 - nper = 1 - perlen = [1000.0] - nstp = [50] - tsmult = [1.2] - delr = delc = 142.0 - top = 0.0 - botm = [-1000.0] - strt = 0.0 - hk = 10.0 - - nouter, ninner = 100, 100 - hclose, rclose, relax = 1e-6, 1e-6, 1.0 - - tdis_rc = [] - for i in range(nper): - tdis_rc.append((perlen[i], nstp[i], tsmult[i])) - - name = ex[idx] - - # build MODFLOW 6 files - ws = dir - sim = flopy.mf6.MFSimulation(sim_name=name, sim_ws=ws) - - # create tdis package - tdis = flopy.mf6.ModflowTdis( - sim, time_units="DAYS", nper=nper, perioddata=tdis_rc - ) - - # create gwf model - gwf = flopy.mf6.MFModel( - sim, - model_type="gwf6", - modelname=name, - model_nam_file=f"{name}.nam", - ) - - # create iterative model solution and register the gwf model with it - ims = flopy.mf6.ModflowIms( - sim, - print_option="SUMMARY", - outer_dvclose=hclose, - outer_maximum=nouter, - under_relaxation="NONE", - inner_maximum=ninner, - inner_dvclose=hclose, - rcloserecord=rclose, - linear_acceleration="CG", - scaling_method="NONE", - reordering_method="NONE", - relaxation_factor=relax, - ) - sim.register_ims_package(ims, [gwf.name]) - - dis = flopy.mf6.ModflowGwfdis( - gwf, - nlay=nlay, - nrow=nrow, - ncol=ncol, - delr=delr, - delc=delc, - top=top, - botm=botm, - idomain=1, - filename=f"{name}.dis", - ) - - # initial conditions - ic = flopy.mf6.ModflowGwfic(gwf, strt=strt, filename=f"{name}.ic") - - # node property flow - npf = flopy.mf6.ModflowGwfnpf( - gwf, - save_flows=True, - icelltype=1, - k=hk, - k33=hk, - filename=f"{name}.npf", - ) - - # storage - sto = flopy.mf6.ModflowGwfsto( - gwf, - save_flows=True, - iconvert=0, - ss=1.0e-5, - sy=0.1, - steady_state={0: False}, - transient={0: True}, - filename=f"{name}.sto", - ) - - # MAW - opth = f"{name}.maw.obs" - wellbottom = -1000 - wellrecarray = [[0, 0.15, wellbottom, 0.0, "THIEM", 1]] - wellconnectionsrecarray = [[0, 0, (0, 50, 50), 0.0, wellbottom, 0.0, 0.0]] - wellperiodrecarray = mawsettings[idx] - mawo_dict = {} - mawo_dict[f"{name}.maw.obs.csv"] = [ - ("m1head", "head", (0,)), - ("m1rate", "rate", (0,)), - ] # is this index one-based? Not if in a tuple - maw = flopy.mf6.ModflowGwfmaw( - gwf, - filename=f"{name}.maw", - print_input=True, - print_head=True, - print_flows=True, - save_flows=True, - observations=mawo_dict, - packagedata=wellrecarray, - connectiondata=wellconnectionsrecarray, - perioddata=wellperiodrecarray, - ) - - # output control - oc = flopy.mf6.ModflowGwfoc( - gwf, - budget_filerecord=f"{name}.cbc", - head_filerecord=f"{name}.hds", - headprintrecord=[ - ("COLUMNS", ncol, "WIDTH", 15, "DIGITS", 6, "GENERAL") - ], - saverecord=[("HEAD", "ALL")], - printrecord=[("HEAD", "ALL"), ("BUDGET", "ALL")], - filename=f"{name}.oc", - ) - - # head observations - obs_data0 = [("head_well_cell", "HEAD", (0, 0, 0))] - obs_recarray = {f"{name}.obs.csv": obs_data0} - obs = flopy.mf6.ModflowUtlobs( - gwf, - pname="head_obs", - filename=f"{name}.obs", - digits=15, - print_input=True, - continuous=obs_recarray, - ) - - return sim, None - - -def eval_maw(sim): - print("evaluating MAW heads...") - - # MODFLOW 6 maw results - idx = sim.idxsim - name = ex[idx] - fpth = os.path.join(sim.simpath, f"{name}.maw.obs.csv") - try: - tc = np.genfromtxt(fpth, names=True, delimiter=",") - except: - assert False, f'could not load data from "{fpth}"' - - if idx == 0: - - # M1RATE should be 2000. - msg = "The injection rate should be 2000. for all times" - assert tc["M1RATE"].min() == tc["M1RATE"].max() == 2000, msg - - elif idx == 1: - - # M1RATE should have a minimum value less than 200 and - # M1HEAD should not exceed 0.400001 - msg = ( - "Injection rate should fall below 200 and the head should not" - "exceed 0.4" - ) - assert tc["M1RATE"].min() < 200.0, msg - assert tc["M1HEAD"].max() < 0.400001, msg - - elif idx == 2: - - # M1RATE should have a minimum value less than 800 - # M1HEAD should not exceed 1.0. - msg = ( - "Min injection rate should be less than 800 and well " - "head should not exceed 1.0" - ) - assert tc["M1RATE"].min() < 800.0 and tc["M1HEAD"].max() < 1.0, msg - - else: - - assert False, f"Test error. idx {idx} not being tested." - - return - - -# - No need to change any code below -@pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), -) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_maw, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_maw, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_maw04.py b/autotest/test_gwf_maw04.py index 403fc8905e4..724b82adb63 100644 --- a/autotest/test_gwf_maw04.py +++ b/autotest/test_gwf_maw04.py @@ -1,52 +1,11 @@ import os -import sys +from types import SimpleNamespace +import flopy import numpy as np -import pytest +from modflow_devtools.case import Case +from pytest_cases import parametrize -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import running_on_CI, testing_framework -from simulation import Simulation - -ex = [ - "maw_iss305a", - "maw_iss305b", - "maw_iss305c", - "maw_iss305d", - "maw_iss305e", - "maw_iss305f", -] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" -cmppth = "mf2005" - -paktest = "maw" - -require_failure = [True for i in range(len(exdirs))] -require_failure[0] = False - -# set travis to True when version 1.13.0 is released -continuous_integration = [True for n in ex] - -# set replace_exe to None to use default executable -replace_exe = None # temporal discretization nper = 2 @@ -63,15 +22,16 @@ xlen = 1000.0 common_ratio = 1.01 nhalf = int(0.5 * ncol) + 1 -first_term = 0.5 * xlen / ((1 - common_ratio**nhalf) / (1 - common_ratio)) +first_term = 0.5 * xlen / ((1 - common_ratio ** nhalf) / (1 - common_ratio)) + delr = np.zeros((ncol), dtype=float) for n in range(nhalf): if n == 0: v = first_term else: - v = first_term * common_ratio**n + v = first_term * common_ratio ** n delr[nhalf + n - 1] = v -delr[: nhalf - 1] = delr[-1 : nhalf - 1 : -1] +delr[: nhalf - 1] = delr[-1: nhalf - 1: -1] # add error to edge cells err = xlen - delr.sum() @@ -105,195 +65,212 @@ radius = 0.25 sradius0 = radius + 0.1 wellq = -100.0 -skin_mult = [0.1, 10.0, 1.0, 0.0, -1.0, 100.0] -condeqn = ["CUMULATIVE", "SKIN", "SKIN", "SKIN", "SPECIFIED", "CUMULATIVE"] -sradius = [sradius0, sradius0, sradius0, sradius0, sradius0, radius0 * 1.5] - -tdis_rc = [] -for idx in range(nper): - tdis_rc.append((perlen[idx], nstp[idx], tsmult[idx])) - +skin_mult = {"a": 0.1, "b": 10.0, "c": 1.0, "d": 0.0, "e": -1.0, "f": 100.0} +condeqn = {"a": "CUMULATIVE", "b": "SKIN", "c": "SKIN", "d": "SKIN", "e": "SPECIFIED", "f": "CUMULATIVE"} +sradius = {"a": sradius0, "b": sradius0, "c": sradius0, "d": sradius0, "e": sradius0, "f": radius0 * 1.5} hclose, rclose = 1e-9, 1e-6 -def build_model(idx, dir): - name = ex[idx] - ws = dir - - # build MODFLOW 6 files - sim = flopy.mf6.MFSimulation( - sim_name=name, version="mf6", exe_name="mf6", sim_ws=ws - ) - # create tdis package - tdis = flopy.mf6.ModflowTdis( - sim, time_units="DAYS", nper=nper, perioddata=tdis_rc - ) - - # create iterative model solution - ims = flopy.mf6.ModflowIms( - sim, inner_dvclose=hclose, rcloserecord=rclose, outer_dvclose=hclose - ) - - # create gwf model - gwf = flopy.mf6.ModflowGwf(sim, modelname=name, save_flows=True) - - # discretization - dis = flopy.mf6.ModflowGwfdis( - gwf, - nlay=nlay, - nrow=nrow, - ncol=ncol, - delr=delr, - delc=delr, - top=top, - botm=botm, - ) - # initial conditions - ic = flopy.mf6.ModflowGwfic(gwf, strt=strt) - - # node property flow - npf = flopy.mf6.ModflowGwfnpf( - gwf, save_flows=False, icelltype=confined, k=hk - ) - # storage - sto = flopy.mf6.ModflowGwfsto( - gwf, - save_flows=False, - iconvert=confined, - ss=ss, - steady_state={0: True}, - transient={1: True}, - ) - # constant head - chd = flopy.mf6.ModflowGwfchd( - gwf, stress_period_data=chd_spd, save_flows=False - ) - # multi-aquifer well - hks = hk * skin_mult[idx] - mpd = [[0, radius, botm[-1], strt, condeqn[idx], 2]] - mcd = [ - [0, 0, (0, nhalf, nhalf), top, botm[0], hks, sradius[idx]], - [0, 1, (1, nhalf, nhalf), botm[0], botm[1], hks, sradius[idx]], +def well4(label): + hks = hk * skin_mult[label] + packagedata = [[0, radius, botm[-1], strt, condeqn[label], 2]] + connectiondata = [ + [0, 0, (0, nhalf, nhalf), top, botm[0], hks, sradius[label]], + [0, 1, (1, nhalf, nhalf), botm[0], botm[1], hks, sradius[label]], ] perioddata = {1: [[0, "RATE", wellq]]} - maw = flopy.mf6.ModflowGwfmaw( - gwf, + return SimpleNamespace( print_input=True, no_well_storage=True, - packagedata=mpd, - connectiondata=mcd, - perioddata=perioddata, + packagedata=packagedata, + connectiondata=connectiondata, + perioddata=perioddata ) - # output control - oc = flopy.mf6.ModflowGwfoc( - gwf, - budget_filerecord=f"{name}.cbc", - head_filerecord=f"{name}.hds", - saverecord=[("HEAD", "ALL"), ("BUDGET", "ALL")], - ) - # build MODFLOW-2005 files - if require_failure[idx]: - mc = None - else: - ws = os.path.join(dir, cmppth) - mc = flopy.modflow.Modflow(name, model_ws=ws, version=cmppth) - dis = flopy.modflow.ModflowDis( - mc, - nlay=nlay, - nrow=nrow, - ncol=ncol, - nper=nper, - perlen=perlen, - nstp=nstp, - tsmult=tsmult, - steady=steady, - delr=delr, - delc=delr, - top=top, - botm=botm, - ) - bas = flopy.modflow.ModflowBas(mc, strt=strt) - lpf = flopy.modflow.ModflowLpf( - mc, laytyp=confined, hk=hk, vka=hk, ss=ss, sy=0 - ) - chd = flopy.modflow.ModflowChd(mc, stress_period_data=chd5_spd) - # mnw2 - # empty mnw2 file to create recarrays - mnw2 = flopy.modflow.ModflowMnw2(mc) - node_data = mnw2.get_empty_node_data(2) - node_data["ztop"] = np.array([top, botm[0]]) - node_data["zbotm"] = np.array([botm[0], botm[1]]) - node_data["i"] = np.array([nhalf, nhalf]) - node_data["j"] = np.array([nhalf, nhalf]) - node_data["wellid"] = np.array(["well1", "well1"]) - node_data["losstype"] = np.array(["skin", "skin"]) - node_data["rw"] = np.array([radius, radius]) - node_data["rskin"] = np.array([sradius[idx], sradius[idx]]) - node_data["kskin"] = np.array([hks, hks]) - dtype = [("wellid", np.unicode_, 20), ("qdes", " dtol: + config.success = False + msg += f"exceeds {dtol}" + assert diffmax < dtol, msg + else: + config.success = True + print(" " + msg) + + case2 = Case( + name="maw02", + krylov="CG", + nlay=1, + nrow=1, + ncol=3, + nper=5, + delr=300, + delc=300, + perlen=5 * [1], + nstp=5 * [1], + tsmult=5 * [1], + well=well2, + strt=100, + hk=1, + nouter=100, + ninner=300, + hclose=1e-9, + rclose=1e-3, + relaxation_factor=1, + compare=False + ) + cases2 = [case2] + + @parametrize(data=cases2, ids=[c.name for c in cases2]) + def case_2(self, tmpdir, targets, data): + name = data.name + ws = str(tmpdir) + sim = flopy.mf6.MFSimulation( + sim_name=name, version="mf6", exe_name=targets["mf6"], sim_ws=ws + ) + + # create tdis package + tdis_rc = [(data.perlen[i], data.nstp[i], data.tsmult[i]) for i in range(data.nper)] + tdis = flopy.mf6.ModflowTdis( + sim, time_units="DAYS", nper=data.nper, perioddata=tdis_rc + ) + + # create gwf model + gwf = flopy.mf6.MFModel( + sim, + model_type="gwf6", + modelname=name, + model_nam_file=f"{name}.nam", + ) + + # create iterative model solution and register the gwf model with it + ims = flopy.mf6.ModflowIms( + sim, + print_option="SUMMARY", + outer_dvclose=data.hclose, + outer_maximum=data.nouter, + under_relaxation="NONE", + inner_maximum=data.ninner, + inner_dvclose=data.hclose, + rcloserecord=data.rclose, + linear_acceleration=data.krylov, + scaling_method="NONE", + reordering_method="NONE", + relaxation_factor=data.relaxation_factor, + ) + sim.register_ims_package(ims, [gwf.name]) + + dis = flopy.mf6.ModflowGwfdis( + gwf, + nlay=data.nlay, + nrow=data.nrow, + ncol=data.ncol, + delr=data.delr, + delc=data.delc, + top=100.0, + botm=0.0, + idomain=1, + filename=f"{name}.dis", + ) + + # initial conditions + ic = flopy.mf6.ModflowGwfic(gwf, strt=data.strt, filename=f"{name}.ic") + + # node property flow + npf = flopy.mf6.ModflowGwfnpf( + gwf, + save_flows=True, + icelltype=1, + k=data.hk, + k33=data.hk, + filename=f"{name}.npf", + ) + # storage + sto = flopy.mf6.ModflowGwfsto( + gwf, + save_flows=True, + iconvert=1, + ss=0.0, + sy=0.1, + steady_state={0: True}, + # transient={1: False}, + filename=f"{name}.sto", + ) + + # chd files + chdlist0 = [] + chdlist0.append([(0, 0, 0), 100.0]) + chdlist0.append([(0, 0, 2), 100.0]) + + chdlist1 = [] + chdlist1.append([(0, 0, 0), 25.0]) + chdlist1.append([(0, 0, 2), 25.0]) + + chdspdict = {0: chdlist0, 1: chdlist1, 2: chdlist0} + chd = flopy.mf6.ModflowGwfchd( + gwf, + stress_period_data=chdspdict, + save_flows=False, + filename=f"{name}.chd", + ) + + # MAW + maw = flopy.mf6.ModflowGwfmaw( + gwf, + filename=f"{name}.maw", + budget_filerecord=f"{name}.maw.cbc", + print_input=True, + print_head=True, + print_flows=True, + save_flows=True, + observations=data.well.observations, + packagedata=data.well.packagedata, + connectiondata=data.well.connectiondata, + perioddata=data.well.perioddata, + pname="MAW-1", + ) + + # output control + oc = flopy.mf6.ModflowGwfoc( + gwf, + budget_filerecord=f"{name}.cbc", + head_filerecord=f"{name}.hds", + headprintrecord=[("COLUMNS", 10, "WIDTH", 15, "DIGITS", 6, "GENERAL")], + saverecord=[("HEAD", "ALL"), ("BUDGET", "ALL")], + printrecord=[("HEAD", "ALL"), ("BUDGET", "ALL")], + filename=f"{name}.oc", + ) + + return data, sim, None, self.eval_2 + + def eval_2(self, config, data): + print("evaluating MAW budgets...") + + shape3d = (data.nlay, data.nrow, data.ncol) + size3d = data.nlay * data.nrow * data.ncol + + # get results from listing file + fpth = os.path.join(config.simpath, f"{os.path.basename(config.name)}.lst") + budl = flopy.utils.Mf6ListBudget( + fpth, budgetkey="MAW-1 BUDGET FOR ENTIRE MODEL AT END OF TIME STEP" + ) + names = list(self.bud_lst) + d0 = budl.get_budget(names=names)[0] + dtype = d0.dtype + nbud = d0.shape[0] + + # get results from cbc file + cbc_bud = ["GWF", "RATE"] + d = np.recarray(nbud, dtype=dtype) + for key in self.bud_lst: + d[key] = 0.0 + fpth = os.path.join(config.simpath, f"{os.path.basename(config.name)}.maw.cbc") + cobj = flopy.utils.CellBudgetFile(fpth, precision="double") + kk = cobj.get_kstpkper() + times = cobj.get_times() + cbc_vals = [] + for idx, (k, t) in enumerate(zip(kk, times)): + for text in cbc_bud: + qin = 0.0 + qout = 0.0 + v = cobj.get_data(kstpkper=k, text=text)[0] + if isinstance(v, np.recarray): + vt = np.zeros(size3d, dtype=float) + wq = [] + for jdx, node in enumerate(v["node"]): + vt[node - 1] += v["q"][jdx] + wq.append(v["q"][jdx]) + v = vt.reshape(shape3d) + if text == cbc_bud[-1]: + cbc_vals.append(wq) + for kk in range(v.shape[0]): + for ii in range(v.shape[1]): + for jj in range(v.shape[2]): + vv = v[kk, ii, jj] + if vv < 0.0: + qout -= vv + else: + qin += vv + d["totim"][idx] = t + d["time_step"][idx] = k[0] + d["stress_period"] = k[1] + key = f"{text}_IN" + d[key][idx] = qin + key = f"{text}_OUT" + d[key][idx] = qout + + maw_vals = [ + [0.000, 0.000], + [-106.11303563809453, -96.22598985147631], + [-110.000, -130.000], + [0.0, -130.000], + [-110.000, -130.000], + ] + + # evaluate if well rates in cbc file are equal to expected values + diffv = [] + for ovs, svs in zip(maw_vals, cbc_vals): + for ov, sv in zip(ovs, svs): + diffv.append(ov - sv) + diffv = np.abs(np.array(diffv)).max() + msg = f"\nmaximum absolute maw rate difference ({diffv})\n" + + # calculate difference between water budget items in the lst and cbc files + diff = np.zeros((nbud, len(self.bud_lst)), dtype=float) + for idx, key in enumerate(self.bud_lst): + diff[:, idx] = d0[key] - d[key] + diffmax = np.abs(diff).max() + msg += f"maximum absolute total-budget difference ({diffmax}) " + + # write summary + fpth = os.path.join( + config.simpath, f"{os.path.basename(config.name)}.bud.cmp.out" + ) + f = open(fpth, "w") + for i in range(diff.shape[0]): + if i == 0: + line = f"{'TIME':>10s}" + for idx, key in enumerate(self.bud_lst): + line += f"{key + '_LST':>25s}" + line += f"{key + '_CBC':>25s}" + line += f"{key + '_DIF':>25s}" + f.write(line + "\n") + line = f"{d['totim'][i]:10g}" + for idx, key in enumerate(self.bud_lst): + line += f"{d0[key][i]:25g}" + line += f"{d[key][i]:25g}" + line += f"{diff[i, idx]:25g}" + f.write(line + "\n") + f.close() + + if diffmax > self.budtol or diffv > self.budtol: + config.success = False + msg += f"\n...exceeds {self.budtol}" + assert diffmax < self.budtol, msg + else: + config.success = True + print(" " + msg) + + case3 = Case( + name="maw03", + krylov="CG", + nlay=1, + nrow=101, + ncol=101, + nper=1, + delr=142, + delc=142, + perlen=[1000], + nstp=[50], + tsmult=[1.2], + strt=0, + hk=10, + nouter=100, + ninner=100, + hclose=1e-6, + rclose=1e-6, + relaxation_factor=1, + compare=False + ) + cases3 = [ + case3.copy_update( + name="maw03a", + well=well3('maw03a'), + ), + case3.copy_update( + name="maw03b", + well=well3('maw03b') + ), + case3.copy_update( + name="maw03c", + well=well3('maw03c') + ) + ] + + @parametrize(data=cases3, ids=[c.name for c in cases3]) + def case_3(self, tmpdir, targets, data): + top = 0.0 + botm = [-1000.0] + + tdis_rc = [] + for i in range(data.nper): + tdis_rc.append((data.perlen[i], data.nstp[i], data.tsmult[i])) + + name = data.name + ws = str(tmpdir) + sim = flopy.mf6.MFSimulation(sim_name=name, sim_ws=ws, exe_name=targets["mf6"]) + + # create tdis package + tdis = flopy.mf6.ModflowTdis( + sim, time_units="DAYS", nper=data.nper, perioddata=tdis_rc + ) + + # create gwf model + gwf = flopy.mf6.MFModel( + sim, + model_type="gwf6", + modelname=name, + model_nam_file=f"{name}.nam", + ) + + # create iterative model solution and register the gwf model with it + ims = flopy.mf6.ModflowIms( + sim, + print_option="SUMMARY", + outer_dvclose=data.hclose, + outer_maximum=data.nouter, + under_relaxation="NONE", + inner_maximum=data.ninner, + inner_dvclose=data.hclose, + rcloserecord=data.rclose, + linear_acceleration=data.krylov, + scaling_method="NONE", + reordering_method="NONE", + relaxation_factor=data.relaxation_factor, + ) + sim.register_ims_package(ims, [gwf.name]) + + dis = flopy.mf6.ModflowGwfdis( + gwf, + nlay=data.nlay, + nrow=data.nrow, + ncol=data.ncol, + delr=data.delr, + delc=data.delc, + top=top, + botm=botm, + idomain=1, + filename=f"{name}.dis", + ) + + # initial conditions + ic = flopy.mf6.ModflowGwfic(gwf, strt=data.strt, filename=f"{name}.ic") + + # node property flow + npf = flopy.mf6.ModflowGwfnpf( + gwf, + save_flows=True, + icelltype=1, + k=data.hk, + k33=data.hk, + filename=f"{name}.npf", + ) + + # storage + sto = flopy.mf6.ModflowGwfsto( + gwf, + save_flows=True, + iconvert=0, + ss=1.0e-5, + sy=0.1, + steady_state={0: False}, + transient={0: True}, + filename=f"{name}.sto", + ) + + # MAW + maw = flopy.mf6.ModflowGwfmaw( + gwf, + filename=f"{name}.maw", + print_input=True, + print_head=True, + print_flows=True, + save_flows=True, + observations=data.well.observations, + packagedata=data.well.packagedata, + connectiondata=data.well.connectiondata, + perioddata=data.well.perioddata, + ) + + # output control + oc = flopy.mf6.ModflowGwfoc( + gwf, + budget_filerecord=f"{name}.cbc", + head_filerecord=f"{name}.hds", + headprintrecord=[ + ("COLUMNS", data.ncol, "WIDTH", 15, "DIGITS", 6, "GENERAL") + ], + saverecord=[("HEAD", "ALL")], + printrecord=[("HEAD", "ALL"), ("BUDGET", "ALL")], + filename=f"{name}.oc", + ) + + # head observations + obs_data0 = [("head_well_cell", "HEAD", (0, 0, 0))] + obs_recarray = {f"{name}.obs.csv": obs_data0} + obs = flopy.mf6.ModflowUtlobs( + gwf, + pname="head_obs", + filename=f"{name}.obs", + digits=15, + print_input=True, + continuous=obs_recarray, + ) + + return data, sim, None, self.eval_3 + + def eval_3(self, config, data): + print("evaluating MAW heads...") + + # MODFLOW 6 maw results + test_name = config.name + case_name = data.name + fpth = os.path.join(config.simpath, f"{test_name}.maw.obs.csv") + tc = np.genfromtxt(fpth, names=True, delimiter=",") + + if case_name == 'a': + + # M1RATE should be 2000. + msg = "The injection rate should be 2000. for all times" + assert tc["M1RATE"].min() == tc["M1RATE"].max() == 2000, msg + + elif case_name == 'b': + + # M1RATE should have a minimum value less than 200 and + # M1HEAD should not exceed 0.400001 + msg = ( + "Injection rate should fall below 200 and the head should not" + "exceed 0.4" + ) + assert tc["M1RATE"].min() < 200.0, msg + assert tc["M1HEAD"].max() < 0.400001, msg + + elif case_name == 'c': + + # M1RATE should have a minimum value less than 800 + # M1HEAD should not exceed 1.0. + msg = ( + "Min injection rate should be less than 800 and well " + "head should not exceed 1.0" + ) + assert tc["M1RATE"].min() < 800.0 and tc["M1HEAD"].max() < 1.0, msg + + # TODO + # case4 = Case( + # name='maw_iss305', + # krylov='CG', + # nlay=2, + # nrow=101, + # ncol=101, + # nper=2, + # delr=142, + # delc=142, + # perlen=[0.0, 365.0], + # nstp=[1, 25], + # tsmult=[1.0, 1.1], + # steady=[True, False], + # well=None, + # strt=0, + # hk=10, + # nouter=100, + # ninner=100, + # hclose=1e-9, + # rclose=1e-6, + # relax=1, + # require_failure=True + # ) + # cases4 = [ + # case4.copy_update({ + # 'name': "maw_iss305a", + # 'well': well4(case4, "CUMULATIVE"), + # 'require_failure': False + # }), + # case4.copy_update({ + # 'name': "maw_iss305b", + # 'well': well4(case4, "SKIN") + # }), + # case4.copy_update({ + # 'name': "maw_iss305c", + # 'well': well4(case4, "SKIN") + # }), + # case4.copy_update({ + # 'name': "maw_iss305d", + # 'well': well4(case4, "SKIN") + # }), + # case4.copy_update({ + # 'name': "maw_iss305e", + # 'well': well4(case4, "SPECIFIED") + # }), + # case4.copy_update({ + # 'name': "maw_iss305f", + # 'well': well4(case4, "CUMULATIVE") + # }) + # ] + + # @parametrize(data=cases4, ids=[c['name'] for c in cases4]) + # def case_4(self, tmpdir, targets, data): + # pass + + # def eval_4(self, sim, data): + # pass diff --git a/autotest/test_gwf_maw_obs.py b/autotest/test_gwf_maw_obs.py index 21ee3503b39..7455949fc37 100644 --- a/autotest/test_gwf_maw_obs.py +++ b/autotest/test_gwf_maw_obs.py @@ -6,39 +6,14 @@ import os -import shutil -import numpy as np -import pytest - -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -import targets - -mf6_exe = os.path.abspath(targets.target_dict["mf6"]) +import flopy newtonoptions = [None, "NEWTON", "NEWTON UNDER_RELAXATION"] ex = "maw_obs" -exdir = os.path.join("temp", ex) -ddir = "data" - -def build_model(): +def build_model(dir, exe): nlay, nrow, ncol = 1, 1, 3 nper = 3 @@ -63,9 +38,9 @@ def build_model(): name = ex # build MODFLOW 6 files - ws = exdir + ws = dir sim = flopy.mf6.MFSimulation( - sim_name=name, version="mf6", exe_name=mf6_exe, sim_ws=ws + sim_name=name, version="mf6", exe_name=exe, sim_ws=ws ) # create tdis package tdis = flopy.mf6.ModflowTdis( @@ -192,18 +167,14 @@ def build_model(): return sim -def test_mf6model(): - # build the models - sim = build_model() - - # write model input +def test_mf6model(function_tmpdir, targets): + mf6 = targets["mf6"] + sim = build_model(str(function_tmpdir), mf6) sim.write_simulation() - - # attempt to run model should fail sim.run_simulation() # ensure that the error msg is contained in the mfsim.lst file - f = open(os.path.join(exdir, "mfsim.lst"), "r") + f = open(str(function_tmpdir / "mfsim.lst"), "r") lines = f.readlines() error_count = 0 expected_msg = False @@ -217,8 +188,8 @@ def test_mf6model(): ) # fix the error and attempt to rerun model - orig_fl = os.path.join(exdir, ex + ".maw.obs") - new_fl = os.path.join(exdir, ex + ".maw.obs.new") + orig_fl = str(function_tmpdir / (ex + ".maw.obs")) + new_fl = str(function_tmpdir / (ex + ".maw.obs.new")) sr = open(orig_fl, "r") sw = open(new_fl, "w") @@ -241,19 +212,3 @@ def test_mf6model(): success, buff = sim.run_simulation() assert success, "model rerun failed" - - shutil.rmtree(exdir, ignore_errors=True) - - -def main(): - test_mf6model() - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_multimvr.py b/autotest/test_gwf_multimvr.py index 59bcef3a48e..93e3d146492 100644 --- a/autotest/test_gwf_multimvr.py +++ b/autotest/test_gwf_multimvr.py @@ -1,30 +1,14 @@ import math import os -import shutil +import flopy import numpy as np import pytest +from flopy.utils.lgrutil import Lgr -import targets +from harness import TestHarness, TestConfig -try: - import flopy - from flopy.utils.lgrutil import Lgr -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation - -mf6exe = os.path.abspath(targets.target_dict["mf6"]) - -name = "gwf" mvr_scens = ["mltmvr", "mltmvr5050", "mltmvr7525"] -ws = os.path.join("temp", name) -exdirs = [f"{ws}-{s}" for s in mvr_scens] sim_workspaces = [] gwf_names = [] @@ -583,9 +567,9 @@ def instantiate_base_simulation(sim_ws, gwfname, gwfnamec): sim_workspaces.append(sim_ws) gwf_names.append(gwfname) sim = flopy.mf6.MFSimulation( - sim_name=name, + sim_name="gwf", version="mf6", - exe_name=mf6exe, + exe_name="mf6", sim_ws=sim_ws, continue_=False, ) @@ -837,7 +821,7 @@ def instantiate_base_simulation(sim_ws, gwfname, gwfnamec): nexg=len(exchange_data), exchangedata=exchange_data, pname="EXG-1", - filename=f"{name}.exg", + filename=f"gwf.exg", ) return sim, gwf, gwfc @@ -982,7 +966,7 @@ def add_sim_mvr(sim, gwfname, gwfnamec, remaining_frac=None): maxpackages=maxpackages, packages=mvrpack_sim, perioddata=mvrspd, - filename=f"{name}.mvr", + filename=f"gwf.mvr", ) @@ -993,8 +977,8 @@ def build_model(idx, sim_ws): scen_conns[idx], parent_mvr_frac[idx], ) - scen_nm_parent = name + "_" + scen_nm + "_p" - scen_nm_child = name + "_" + scen_nm + "_c" + scen_nm_parent = "gwf_" + scen_nm + "_p" + scen_nm_child = "gwf_" + scen_nm + "_c" sim, gwf, gwfc = instantiate_base_simulation( sim_ws, scen_nm_parent, scen_nm_child ) @@ -1021,9 +1005,9 @@ def check_simulation_output(sim): gwf_srch_str2 = " WATER MOVER PACKAGE (MVR) FLOW RATES " sim_srch_str = " WATER MOVER PACKAGE (MVR) FLOW RATES " - # cur_ws, gwfparent = exdirs[idx], gwf_names[idx] - cur_ws = exdirs[idx] - gwfparent = name + "_" + mvr_scens[idx] + "_p" + # cur_ws, gwfparent = ex[idx], gwf_names[idx] + cur_ws = sim.simpath + gwfparent = "gwf_" + mvr_scens[idx] + "_p" with open(os.path.join(cur_ws, gwfparent + ".lst"), "r") as gwf_lst, open( os.path.join(cur_ws, "mfsim.lst"), "r" ) as sim_lst: @@ -1130,48 +1114,19 @@ def check_simulation_output(sim): ) -# - No need to change any code below - - @pytest.mark.parametrize( - "idx, exdir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(mvr_scens)), ) -def test_mf6model(idx, exdir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, exdir) - - test.run_mf6( - Simulation( - exdir, +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run( + TestConfig( + name=name, + exes=targets, exfunc=check_simulation_output, idxsim=idx, - ) + ), + str(function_tmpdir) ) - - -def main(): - # initialize testing framework - test = testing_framework() - - for idx, exdir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, exdir) - sim = Simulation( - exdir, - exfunc=check_simulation_output, - idxsim=idx, - ) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_mvr01.py b/autotest/test_gwf_mvr01.py index d971945a7c7..c6a53c327d0 100644 --- a/autotest/test_gwf_mvr01.py +++ b/autotest/test_gwf_mvr01.py @@ -1,23 +1,13 @@ import os +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig name = "gwf_mvr01" -ws = os.path.join("temp", name) -exdirs = [ws] - +ex = [name] def build_model(idx, dir): # static model data @@ -45,7 +35,7 @@ def build_model(idx, dir): # build MODFLOW 6 files sim = flopy.mf6.MFSimulation( - sim_name=name, version="mf6", exe_name="mf6", sim_ws=ws + sim_name=name, version="mf6", exe_name="mf6", sim_ws=str(dir) ) # create tdis package tdis = flopy.mf6.ModflowTdis( @@ -453,39 +443,14 @@ def eval_model(sim): ) assert records[24].shape == (0,) - return -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_model, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_model, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_model, idxsim=idx), ws) diff --git a/autotest/test_gwf_newton01.py b/autotest/test_gwf_newton01.py index ca733eba833..8e7efdb1b9d 100644 --- a/autotest/test_gwf_newton01.py +++ b/autotest/test_gwf_newton01.py @@ -1,26 +1,12 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["newton01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" - nlay = 2 nrow, ncol = 3, 3 top = 20 @@ -31,10 +17,7 @@ chdloc = [(1, i, j) for i in range(nrow) for j in range(ncol)] chd = 7.0 strt = chd - -# recharge data rch = 1.0 - oname = "head_obs.csv" obs_recarray = {oname: [("h1", "HEAD", (0, 1, 1)), ("h2", "HEAD", (1, 1, 1))]} @@ -125,40 +108,13 @@ def eval_head(sim): msg = f"head in layer 2 != 7. ({v['H2']})" assert np.allclose(v["H2"], 7.0), msg - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_head)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_head) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, tmpdir, targets): + ws = str(tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_head), ws) diff --git a/autotest/test_gwf_noptc01.py b/autotest/test_gwf_noptc01.py index 2addf94f33e..f6724d2ec91 100644 --- a/autotest/test_gwf_noptc01.py +++ b/autotest/test_gwf_noptc01.py @@ -1,36 +1,13 @@ import os -import numpy as np +import flopy import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import running_on_CI, testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["gwf_noptc01", "gwf_noptc02", "gwf_noptc03"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) - no_ptcrecords = ["FIRST", "ALL", None] - -ddir = "data" - -## run all examples on Travis -continuous_integration = [True for idx in range(len(exdirs))] - -# set replace_exe to None to use default executable -# replace_exe = {'mf2005': 'mf2005devdbl'} -replace_exe = None - -htol = [None for idx in range(len(exdirs))] +htol = [None for idx in range(len(ex))] # static model data # temporal discretization @@ -156,49 +133,12 @@ def build_model(idx, dir): return sim, mc -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # determine if running on CI infrastructure - is_CI = running_on_CI() - r_exe = None - if not is_CI: - if replace_exe is not None: - r_exe = replace_exe - - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - if is_CI and not continuous_integration[idx]: - return - test.run_mf6(Simulation(dir, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, idxsim=idx) - test.run_mf6(sim) - - return - - -# use python testmf6_csub_sub03.py --mf2005 mf2005devdbl -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, idxsim=idx), ws) diff --git a/autotest/test_gwf_npf01_75x75.py b/autotest/test_gwf_npf01_75x75.py index 74ca2cb494d..3ec7b207306 100644 --- a/autotest/test_gwf_npf01_75x75.py +++ b/autotest/test_gwf_npf01_75x75.py @@ -1,29 +1,16 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["npf01a_75x75", "npf01b_75x75"] top = [100.0, 0.0] laytyp = [1, 0] ss = [0.0, 1.0e-4] sy = [0.1, 0.0] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" def build_model(idx, dir): @@ -205,35 +192,10 @@ def build_model(idx, dir): # - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models_legacy(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models_legacy(build_model, idx, dir) - sim = Simulation(dir) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestHarness() + test.build(build_model, idx, str(function_tmpdir)) + test.run(TestConfig(name=name, exes=targets), str(function_tmpdir)) diff --git a/autotest/test_gwf_npf02_rewet.py b/autotest/test_gwf_npf02_rewet.py index 353b85bd9cb..b49bd0a661b 100644 --- a/autotest/test_gwf_npf02_rewet.py +++ b/autotest/test_gwf_npf02_rewet.py @@ -1,25 +1,12 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["npf02_hreweta", "npf02_hrewetb", "npf02_hrewetc", "npf02_hrewetd"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" ncols = [[15], [10, 5], [15], [10, 5]] nlays = [1, 1, 3, 3] @@ -349,42 +336,13 @@ def eval_hds(sim): sim.success = True print(" " + msg) - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_hds, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_hds, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_hds, idxsim=idx), ws) diff --git a/autotest/test_gwf_npf03_sfr.py b/autotest/test_gwf_npf03_sfr.py index ce3cc623fb1..53c2c764866 100644 --- a/autotest/test_gwf_npf03_sfr.py +++ b/autotest/test_gwf_npf03_sfr.py @@ -1,37 +1,18 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import running_on_CI, testing_framework -from simulation import Simulation +from conftest import get_project_root_path +from harness import TestHarness, TestConfig ex = ["npf03_sfra", "npf03_sfrb"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" - -# run all examples on CI -continuous_integration = [True for idx in range(len(exdirs))] -# continuous_integration = [False for idx in range(len(exdirs))] - -# read hk data -fpth = os.path.join(ddir, "npf03_hk.ref") +fpth = str(get_project_root_path() / "autotest" / "data" / "npf03_hk.ref") shape = (50, 108) hk = flopy.utils.Util2d.load_txt(shape, fpth, dtype=float, fmtin="(FREE)") n1 = hk.shape[1] nd = 40 - ncols = [[n1], [n1 - nd, nd]] # static model data @@ -5794,47 +5775,14 @@ def eval_hds(sim): sim.success = True print(" " + msg) - return - -# - No need to change any code below +@pytest.mark.slow @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # determine if running on CI infrastructure - is_CI = running_on_CI() - - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - if is_CI and not continuous_integration[idx]: - return - test.run_mf6(Simulation(dir, exfunc=eval_hds, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_hds, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_hds, idxsim=idx), ws) diff --git a/autotest/test_gwf_npf04_spdis.py b/autotest/test_gwf_npf04_spdis.py index 34e4e2a9ceb..b75e4650479 100644 --- a/autotest/test_gwf_npf04_spdis.py +++ b/autotest/test_gwf_npf04_spdis.py @@ -9,28 +9,15 @@ """ import os -import sys +import flopy import numpy as np import pytest +from flopy.utils.lgrutil import Lgr -try: - import flopy - from flopy.utils.lgrutil import Lgr -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["npf04"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) - namea = "a" nameb = "b" @@ -224,42 +211,13 @@ def eval_mf6(sim): errmsg = f"min or max residual too large {res.min()} {res.max()}" assert np.allclose(res, 0.0, atol=1.0e-6), errmsg - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_mf6, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_mf6, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_mf6, idxsim=idx), ws) diff --git a/autotest/test_gwf_npf05_anisotropy.py b/autotest/test_gwf_npf05_anisotropy.py index e9e9e0d4048..6c1e897c19e 100644 --- a/autotest/test_gwf_npf05_anisotropy.py +++ b/autotest/test_gwf_npf05_anisotropy.py @@ -5,34 +5,14 @@ """ import os -import sys +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["npf05a"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) def build_model(idx, dir): @@ -165,39 +145,14 @@ def eval_model(sim): ] answer = np.array(answer) assert np.allclose(heads.flatten(), answer) - return -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_model, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_model, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_model, idxsim=idx), ws) diff --git a/autotest/test_gwf_npf_tvk01.py b/autotest/test_gwf_npf_tvk01.py index 53ca8c37a43..1d40f1c65e3 100644 --- a/autotest/test_gwf_npf_tvk01.py +++ b/autotest/test_gwf_npf_tvk01.py @@ -1,36 +1,12 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation - -ex = [ - "tvk01", -] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" +from harness import TestHarness, TestConfig +ex = ["tvk01"] time_varying_k = [1.0, 10.0] @@ -165,8 +141,7 @@ def build_model(idx, dir): def eval_model(sim): print("evaluating model...") - name = ex[sim.idxsim] - gwfname = "gwf_" + name + gwfname = "gwf_" + sim.name # head fpth = os.path.join(sim.simpath, f"{gwfname}.hds") @@ -185,7 +160,7 @@ def eval_model(sim): assert False, f'could not load data from "{fpth}"' # This is the answer to this problem. - hk = time_varying_k[sim.idxsim] + hk = time_varying_k[0] delc = 1.0 delr = 1.0 delz = 1.0 @@ -203,39 +178,13 @@ def eval_model(sim): # comment when done testing # assert False - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_model, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_model, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_model, idxsim=0), ws) diff --git a/autotest/test_gwf_npf_tvk02.py b/autotest/test_gwf_npf_tvk02.py index 2cb79d6acca..41d7f3f2178 100644 --- a/autotest/test_gwf_npf_tvk02.py +++ b/autotest/test_gwf_npf_tvk02.py @@ -1,35 +1,12 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation - -ex = [ - "tvk02", -] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" +from harness import TestHarness, TestConfig + +ex = ["tvk02"] def build_model(idx, dir): @@ -184,8 +161,7 @@ def build_model(idx, dir): def eval_model(sim): print("evaluating model...") - name = ex[sim.idxsim] - gwfname = "gwf_" + name + gwfname = "gwf_" + sim.name # head fpth = os.path.join(sim.simpath, f"{gwfname}.hds") @@ -228,39 +204,13 @@ def eval_model(sim): # comment when done testing # assert False - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_model, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_model, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_model, idxsim=0), ws) diff --git a/autotest/test_gwf_npf_tvk03.py b/autotest/test_gwf_npf_tvk03.py index 20d47db9c75..fc973c646f6 100644 --- a/autotest/test_gwf_npf_tvk03.py +++ b/autotest/test_gwf_npf_tvk03.py @@ -1,35 +1,12 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation - -ex = [ - "tvk03", -] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" +from harness import TestHarness, TestConfig + +ex = ["tvk03"] def build_model(idx, dir): @@ -184,8 +161,7 @@ def build_model(idx, dir): def eval_model(sim): print("evaluating model...") - name = ex[sim.idxsim] - gwfname = "gwf_" + name + gwfname = "gwf_" + sim.name # head fpth = os.path.join(sim.simpath, f"{gwfname}.hds") @@ -228,39 +204,13 @@ def eval_model(sim): # comment when done testing # assert False - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_model, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_model, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_model, idxsim=0), ws) diff --git a/autotest/test_gwf_npf_tvk04.py b/autotest/test_gwf_npf_tvk04.py index eef8bff16f0..2be457e9c8a 100644 --- a/autotest/test_gwf_npf_tvk04.py +++ b/autotest/test_gwf_npf_tvk04.py @@ -1,36 +1,12 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation - -ex = [ - "tvk05", -] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" +from harness import TestHarness, TestConfig +ex = ["tvk05"] time_varying_k = [1.0, 10.0] @@ -182,11 +158,9 @@ def build_model(idx, dir): def eval_model(sim): print("evaluating model...") - name = ex[sim.idxsim] - # budget try: - fname = f"gwf_{name}.lst" + fname = f"gwf_{sim.name}.lst" ws = sim.simpath fname = os.path.join(ws, fname) lst = flopy.utils.Mf6ListBudget( @@ -209,39 +183,13 @@ def eval_model(sim): errmsg = f"Expect higher flow rate in period 2 compared to period 1, but found equal or higher flow rate in period 1" assert 2.0 * sp_x[0][8] < sp_x[1][8], errmsg - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_model, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_model, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() \ No newline at end of file +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_model, idxsim=0), ws) diff --git a/autotest/test_gwf_npf_tvk05.py b/autotest/test_gwf_npf_tvk05.py index 44b265f99d9..6d043299db8 100644 --- a/autotest/test_gwf_npf_tvk05.py +++ b/autotest/test_gwf_npf_tvk05.py @@ -1,36 +1,12 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation - -ex = [ - "tvk05", -] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" +from harness import TestHarness, TestConfig +ex = ["tvk05"] time_varying_k = [1.0, 10.0] @@ -183,11 +159,9 @@ def build_model(idx, dir): def eval_model(sim): print("evaluating model...") - name = ex[sim.idxsim] - # budget try: - fname = f"gwf_{name}.lst" + fname = f"gwf_{sim.name}.lst" ws = sim.simpath fname = os.path.join(ws, fname) lst = flopy.utils.Mf6ListBudget( @@ -210,39 +184,13 @@ def eval_model(sim): errmsg = f"Period 2 budget should be exactly the same as period 1" assert sp_x[0][8] == sp_x[1][8], errmsg - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_model, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_model, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() \ No newline at end of file +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_model, idxsim=0), ws) diff --git a/autotest/test_gwf_obs01.py b/autotest/test_gwf_obs01.py index 39256e24893..c621ee1b519 100644 --- a/autotest/test_gwf_obs01.py +++ b/autotest/test_gwf_obs01.py @@ -1,34 +1,13 @@ import os +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig cell_dimensions = (300,) ex = [f"gwf_obs01{chr(ord('a') + idx)}" for idx in range(len(cell_dimensions))] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" - h0, h1 = 1.0, 0.0 @@ -164,42 +143,14 @@ def eval_model(sim): msg = "simulated head observations do not match with known solution." assert np.allclose(hres, obs), msg - return - -# - No need to change any code below +@pytest.mark.slow @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build all of the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_model, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build all of the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_model, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, tmpdir, targets): + ws = str(tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_model, idxsim=idx), ws) diff --git a/autotest/test_gwf_obs02.py b/autotest/test_gwf_obs02.py index 5e2cb0aff7b..588c9164d45 100644 --- a/autotest/test_gwf_obs02.py +++ b/autotest/test_gwf_obs02.py @@ -4,35 +4,14 @@ """ import os +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig cell_dimensions = (300,) ex = ["gwf_obs02"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" - h0, h1 = 1.0, 0.0 nlay, nrow, ncol = 1, 10, 10 @@ -147,10 +126,9 @@ def build_model(idx, dir): def eval_model(sim): print("evaluating model observations...") - name = ex[sim.idxsim] headcsv = np.empty((nlay, nrow, ncol), dtype=float) for i in range(nrow): - fname = f"{name}.{i}.obs.csv" + fname = f"{sim.name}.{i}.obs.csv" print(f"Loading and testing {fname}") fname = os.path.join(sim.simpath, fname) rec = np.genfromtxt(fname, names=True, delimiter=",", deletechars="") @@ -164,7 +142,7 @@ def eval_model(sim): assert obsname_true == obsname_found, errmsg headcsv[0, i, :] = np.array(rec.tolist()[1:]) - fn = os.path.join(sim.simpath, f"{name}.hds") + fn = os.path.join(sim.simpath, f"{sim.name}.hds") hobj = flopy.utils.HeadFile(fn) headbin = hobj.get_data() @@ -172,42 +150,13 @@ def eval_model(sim): headcsv, headbin ), "headcsv not equal head from binary file" - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build all of the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_model, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build all of the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_model, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_model, idxsim=0), ws) diff --git a/autotest/test_gwf_ptc01.py b/autotest/test_gwf_ptc01.py index af8197c9f7f..86d8549d4b7 100644 --- a/autotest/test_gwf_ptc01.py +++ b/autotest/test_gwf_ptc01.py @@ -1,28 +1,15 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from conftest import get_project_root_path +from harness import TestHarness, TestConfig ex = ["ptc01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" - -# read bottom data -fpth = os.path.join(ddir, "nwtp03_bot.ref") +data_path = get_project_root_path() / "autotest" / "data" +fpth = str(data_path / "nwtp03_bot.ref") botm = np.loadtxt(fpth, dtype=float) nlay = 1 nrow, ncol = botm.shape @@ -37,7 +24,7 @@ strt = botm + 20.0 # read recharge data -fpth = os.path.join(ddir, "nwtp03_rch.ref") +fpth = str(data_path / "nwtp03_rch.ref") rch = np.loadtxt(fpth, dtype=float) @@ -156,39 +143,13 @@ def build_model(idx, dir): return sim, mc -# - No need to change any code below +@pytest.mark.slow @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for dir in exdirs: - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets), ws) diff --git a/autotest/test_gwf_rch01.py b/autotest/test_gwf_rch01.py index f36d6465411..3a36af7ade3 100644 --- a/autotest/test_gwf_rch01.py +++ b/autotest/test_gwf_rch01.py @@ -9,35 +9,15 @@ """ import os -import sys +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["rch01a", "rch01b", "rch01c"] irch = [None, 0, [1, 1, 0, 1, 1]] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) def build_model(idx, dir): @@ -160,39 +140,13 @@ def eval_model(sim): hobj = flopy.utils.HeadFile(fpth, precision="double") heads = hobj.get_alldata() - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_model, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_model, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_model, idxsim=idx), ws) diff --git a/autotest/test_gwf_rch02.py b/autotest/test_gwf_rch02.py index 69f0d2645cd..ccaa20a9a2f 100644 --- a/autotest/test_gwf_rch02.py +++ b/autotest/test_gwf_rch02.py @@ -5,34 +5,14 @@ """ import os -import sys +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["rch02"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) def build_model(idx, dir): @@ -152,39 +132,13 @@ def eval_model(sim): hobj = flopy.utils.HeadFile(fpth, precision="double") heads = hobj.get_alldata() - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_model, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_model, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_model, idxsim=idx), ws) diff --git a/autotest/test_gwf_rch03.py b/autotest/test_gwf_rch03.py index b4ffea4e22d..40ec7155bd8 100644 --- a/autotest/test_gwf_rch03.py +++ b/autotest/test_gwf_rch03.py @@ -5,34 +5,14 @@ """ import os -import sys +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["rch03"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) def build_model(idx, dir): @@ -178,39 +158,13 @@ def eval_model(sim): hobj = flopy.utils.HeadFile(fpth, precision="double") heads = hobj.get_alldata() - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_model, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_model, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_model, idxsim=idx), ws) diff --git a/autotest/test_gwf_returncodes.py b/autotest/test_gwf_returncodes.py index 9201054d3df..3eda6b7ef76 100644 --- a/autotest/test_gwf_returncodes.py +++ b/autotest/test_gwf_returncodes.py @@ -1,25 +1,11 @@ import os -import shutil import subprocess import sys +import flopy import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -import targets - -mf6_exe = os.path.abspath(targets.target_dict["mf6"]) name = "gwf_ret_codes01" -base_ws = os.path.join("temp", name) -if not os.path.isdir(base_ws): - os.makedirs(base_ws, exist_ok=True) app = "mf6" if sys.platform.lower() == "win32": app += ".exe" @@ -40,7 +26,7 @@ def run_mf6(argv, ws): return proc.returncode, buff -def get_sim(ws, idomain, continue_flag=False, nouter=500): +def get_sim(ws, exe, idomain, continue_flag=False, nouter=500): # static model data # temporal discretization nper = 1 @@ -66,7 +52,7 @@ def get_sim(ws, idomain, continue_flag=False, nouter=500): sim = flopy.mf6.MFSimulation( sim_name=name, version="mf6", - exe_name=mf6_exe, + exe_name=exe, sim_ws=ws, continue_=continue_flag, ) @@ -143,17 +129,17 @@ def get_sim(ws, idomain, continue_flag=False, nouter=500): return sim -def normal_termination(): - ws = os.path.join(base_ws, "normal_termination") +def normal_termination(dir, exe): + ws = os.path.join(dir, "normal_termination") # get the simulation - sim = get_sim(ws, idomain=1) + sim = get_sim(ws, exe, idomain=1) # write the input files sim.write_simulation() # run the simulation - returncode, buff = run_mf6([mf6_exe], ws) + returncode, buff = run_mf6([exe], ws) if returncode != 0: msg = ( "The run should have been successful but it terminated " @@ -161,79 +147,69 @@ def normal_termination(): ) raise ValueError(msg) - # clean up working directory - clean(ws) - - return - -def converge_fail_continue(): - ws = os.path.join(base_ws, "converge_fail_continue") +def converge_fail_continue(dir, exe): + ws = os.path.join(dir, "converge_fail_continue") # get the simulation - sim = get_sim(ws, idomain=1, continue_flag=True, nouter=1) + sim = get_sim(ws, exe, idomain=1, continue_flag=True, nouter=1) # write the input files sim.write_simulation() # run the simulation - returncode, buff = run_mf6([mf6_exe], ws) + returncode, buff = run_mf6([exe], ws) msg = ( "The run should have been successful even though it failed, because" " the continue flag was set. But a non-zero error code was " "found: {}".format(returncode) ) assert returncode == 0, msg - return -def converge_fail_nocontinue(): - ws = os.path.join(base_ws, "converge_fail_nocontinue") +def converge_fail_nocontinue(dir, exe): + ws = os.path.join(dir, "converge_fail_nocontinue") with pytest.raises(RuntimeError): # get the simulation - sim = get_sim(ws, idomain=1, continue_flag=False, nouter=1) + sim = get_sim(ws, exe, idomain=1, continue_flag=False, nouter=1) # write the input files sim.write_simulation() # run the simulation - returncode, buff = run_mf6([mf6_exe], ws) + returncode, buff = run_mf6([exe], ws) msg = "This run should fail with a returncode of 1" if returncode == 1: - clean(ws) raise RuntimeError(msg) -def idomain_runtime_error(): - ws = os.path.join(base_ws, "idomain_runtime_error") +def idomain_runtime_error(dir, exe): + ws = os.path.join(dir, "idomain_runtime_error") with pytest.raises(RuntimeError): # get the simulation - sim = get_sim(ws, idomain=0) + sim = get_sim(ws, exe, idomain=0) # write the input files sim.write_simulation() # run the simulation - returncode, buff = run_mf6([mf6_exe], ws) + returncode, buff = run_mf6([exe], ws) msg = f"could not run {sim.name}" if returncode != 0: err_str = "Ensure IDOMAIN array has some" err = any(err_str in s for s in buff) if err: - clean(ws) raise RuntimeError(msg) else: msg += " but IDOMAIN ARRAY ERROR not returned" raise ValueError(msg) -def unknown_keyword_error(): - ws = base_ws - - with pytest.raises(RuntimeError): - returncode, buff = run_mf6([mf6_exe, "--unknown_keyword"], ws) +def unknown_keyword_error(dir, exe): + with pytest.raises((RuntimeError, ValueError)): + returncode, buff = run_mf6([exe, "--unknown_keyword"], dir) msg = "could not run unknown_keyword" if returncode != 0: err_str = f"{app}: illegal option" @@ -245,10 +221,8 @@ def unknown_keyword_error(): raise ValueError(msg) -def run_argv(arg, return_str): - ws = base_ws - - returncode, buff = run_mf6([mf6_exe, arg], ws) +def run_argv(arg, return_str, tempdir, exe): + returncode, buff = run_mf6([exe, arg], tempdir) if returncode == 0: found_str = any(return_str in s for s in buff) if not found_str: @@ -259,62 +233,43 @@ def run_argv(arg, return_str): raise RuntimeError(msg) -def help_argv(): +def help_argv(dir, exe): for arg in ["-h", "--help", "-?"]: return_str = f"{app} [options] retrieve program information" - run_argv(arg, return_str) + run_argv(arg, return_str, dir, exe) -def version_argv(): +def version_argv(dir, exe): for arg in ["-v", "--version"]: return_str = f"{app}: 6" - run_argv(arg, return_str) + run_argv(arg, return_str, dir, exe) -def develop_argv(): +def develop_argv(dir, exe): for arg in ["-dev", "--develop"]: return_str = f"{app}: develop version" - run_argv(arg, return_str) + run_argv(arg, return_str, dir, exe) -def compiler_argv(): +def compiler_argv(dir, exe): for arg in ["-c", "--compiler"]: return_str = f"{app}: MODFLOW 6 compiled" - run_argv(arg, return_str) - - -def clean(dir_pth): - print(f"Cleaning up {dir_pth}") - shutil.rmtree(dir_pth) + run_argv(arg, return_str, dir, exe) @pytest.mark.parametrize( "fn", ( - "idomain_runtime_error()", - "unknown_keyword_error()", - "normal_termination()", - "converge_fail_nocontinue()", - "help_argv()", - "version_argv()", - "develop_argv()", - "compiler_argv()", + "idomain_runtime_error", + "unknown_keyword_error", + "normal_termination", + "converge_fail_nocontinue", + "help_argv", + "version_argv", + "develop_argv", + "compiler_argv", ), ) -def test_main(fn): - eval(fn) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - idomain_runtime_error() - unknown_keyword_error() - normal_termination() - converge_fail_nocontinue() - help_argv() - version_argv() - develop_argv() - compiler_argv() - clean(base_ws) +def test_main(fn, function_tmpdir, targets): + mf6 = targets.as_dict()["mf6"] + eval(fn)(function_tmpdir, mf6) diff --git a/autotest/test_gwf_sfr_badfactor.py b/autotest/test_gwf_sfr_badfactor.py index 86c4751f93a..23677308164 100644 --- a/autotest/test_gwf_sfr_badfactor.py +++ b/autotest/test_gwf_sfr_badfactor.py @@ -1,33 +1,11 @@ -import os -import shutil -import subprocess -import sys - +import flopy import numpy as np -import pytest - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -import targets -from framework import testing_framework -from simulation import Simulation - -mf6_exe = os.path.abspath(targets.target_dict["mf6"]) paktest = "sfr" testname = "ts_sfr01" -testdir = os.path.join("temp", testname) -os.makedirs(testdir, exist_ok=True) -everything_was_successful = True -def build_model(timeseries=False): +def build_model(ws, exe, timeseries=False): # static model data # temporal discretization nper = 1 @@ -57,9 +35,8 @@ def build_model(timeseries=False): # build MODFLOW 6 files name = testname - ws = testdir sim = flopy.mf6.MFSimulation( - sim_name=name, version="mf6", exe_name=mf6_exe, sim_ws=ws + sim_name=name, version="mf6", exe_name=exe, sim_ws=ws ) # create tdis package tdis = flopy.mf6.ModflowTdis( @@ -529,40 +506,16 @@ def build_model(timeseries=False): return sim -# - No need to change any code below -def test_mf6model(): - # build and run the test model - sim = build_model() - sim.write_simulation() - sim.run_simulation() - - # ensure that the error msg is contained in the mfsim.lst file - f = open(os.path.join(testdir, "mfsim.lst"), "r") - lines = f.readlines() - error_count = 0 - expected_msg = False - for line in lines: - if "cprior" and "divflow not within" in line: - expected_msg = True - error_count += 1 - - assert error_count == 1, ( - "error count = " + str(error_count) + "but should equal 1" - ) - - print("Finished running surfdep check") - - return - +def test_mf6model(function_tmpdir, targets): + mf6 = targets.mf6 -def main(): # build and run the test model - sim = build_model() + sim = build_model(str(function_tmpdir), mf6) sim.write_simulation() sim.run_simulation() # ensure that the error msg is contained in the mfsim.lst file - f = open(os.path.join(testdir, "mfsim.lst"), "r") + f = open(str(function_tmpdir / "mfsim.lst"), "r") lines = f.readlines() error_count = 0 expected_msg = False @@ -576,13 +529,3 @@ def main(): ) print("Finished running surfdep check") - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_sfr_evap.py b/autotest/test_gwf_sfr_evap.py index 8f57ab4c9bd..9275c41f7cf 100644 --- a/autotest/test_gwf_sfr_evap.py +++ b/autotest/test_gwf_sfr_evap.py @@ -1,28 +1,14 @@ # Test evap in SFR reaches (no interaction with gwf) -# Imports - import os -import sys +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["sfr-evap"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) # Model units @@ -448,36 +434,12 @@ def eval_results(sim): assert np.allclose(stored_strm_evap_r, sim_evap_r, atol=1e-4), msg -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_results, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_results, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_results, idxsim=idx), ws) diff --git a/autotest/test_gwf_sfr_npoint01.py b/autotest/test_gwf_sfr_npoint01.py index a63b85f88fb..8342c300b75 100644 --- a/autotest/test_gwf_sfr_npoint01.py +++ b/autotest/test_gwf_sfr_npoint01.py @@ -1,25 +1,13 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation - -sys.path.append("scripts") from cross_section_functions import get_depths +from harness import TestHarness, TestConfig paktest = "sfr" - ex = [ "sfr_npt01a", "sfr_npt01b", @@ -31,7 +19,6 @@ "sfr_npt01h", "sfr_npt01i", ] -exdirs = [os.path.join("temp", s) for s in ex] xsect_types = ( "wide", @@ -298,12 +285,10 @@ def build_model(idx, ws): return sim, None -def eval_npointq(sim): - idx = sim.idxsim - name = ex[idx] - print("evaluating n-point cross-section results..." f"({name})") +def eval_npointq(sim, idx): + print("evaluating n-point cross-section results..." f"({sim.name})") - obs_pth = os.path.join(exdirs[idx], f"{name}.sfr.obs.csv") + obs_pth = os.path.join(sim.simpath, f"{sim.name}.sfr.obs.csv") obs = flopy.utils.Mf6Obs(obs_pth).get_data() assert np.allclose( @@ -327,51 +312,21 @@ def eval_npointq(sim): f"calculated depth: {d}" ) - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, exdir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, exdir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, exdir) - - # run the test models - test.run_mf6( - Simulation( - exdir, - exfunc=eval_npointq, +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run( + TestConfig( + name=name, + exes=targets, + exfunc=lambda s: eval_npointq(s, idx), idxsim=idx, - ) + ), + ws ) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test models - for idx, exdir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, exdir) - - sim = Simulation( - exdir, - exfunc=eval_npointq, - idxsim=idx, - ) - test.run_mf6(sim) - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_sfr_npoint02.py b/autotest/test_gwf_sfr_npoint02.py index d54d404009f..f39115f6249 100644 --- a/autotest/test_gwf_sfr_npoint02.py +++ b/autotest/test_gwf_sfr_npoint02.py @@ -1,25 +1,16 @@ import os +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig paktest = "sfr" ex = [ "sfr_npt02a", ] -exdirs = [os.path.join("temp", s) for s in ex] # temporal discretization nper = 10 @@ -218,11 +209,10 @@ def build_model(idx, ws): def eval_npointdepth(sim): - idx = sim.idxsim - name = ex[idx] + name = sim.name print("evaluating n-point cross-section results..." f"({name})") - obs_pth = os.path.join(exdirs[idx], f"{name}.sfr.obs.csv") + obs_pth = os.path.join(sim.simpath, f"{name}.sfr.obs.csv") obs = flopy.utils.Mf6Obs(obs_pth).get_data() assert np.allclose( @@ -238,51 +228,21 @@ def eval_npointdepth(sim): obs["DEPTH"], d ), "sfr depth not equal to calculated depth" - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, exdir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, exdir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, exdir) - - # run the test models - test.run_mf6( - Simulation( - exdir, +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run( + TestConfig( + name=name, + exes=targets, exfunc=eval_npointdepth, - idxsim=idx, - ) + idxsim=0, + ), + ws ) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test models - for idx, exdir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, exdir) - - sim = Simulation( - exdir, - exfunc=eval_npointdepth, - idxsim=idx, - ) - test.run_mf6(sim) - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_sfr_npoint03.py b/autotest/test_gwf_sfr_npoint03.py index b69e4d88a81..e834e43f0ba 100644 --- a/autotest/test_gwf_sfr_npoint03.py +++ b/autotest/test_gwf_sfr_npoint03.py @@ -1,25 +1,13 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation - -sys.path.append("scripts") from cross_section_functions import calculate_rectchan_mannings_discharge +from harness import TestHarness, TestConfig paktest = "sfr" - ex = [ "sfr_npt03a", "sfr_npt03b", @@ -29,7 +17,6 @@ "sfr_npt03f", "sfr_npt03g", ] -exdirs = [os.path.join("temp", s) for s in ex] simulated_depths = ( 0.5, @@ -281,69 +268,37 @@ def build_models(idx, ws): def eval_npointdepth(sim): - idx = sim.idxsim - name = ex[idx] - print("evaluating n-point cross-section results..." f"({name})") + print("evaluating n-point cross-section results..." f"({sim.name})") - obs_pth0 = os.path.join(exdirs[idx], f"{name}.sfr.obs.csv") + obs_pth0 = os.path.join(sim.simpath, f"{sim.name}.sfr.obs.csv") obs0 = np.genfromtxt(obs_pth0, names=True, delimiter=",") - obs_pth1 = os.path.join(exdirs[idx], "mf6", f"{name}.sfr.obs.csv") + obs_pth1 = os.path.join(sim.simpath, "mf6", f"{sim.name}.sfr.obs.csv") obs1 = np.genfromtxt(obs_pth1, names=True, delimiter=",") q0 = obs0["OUTFLOW_DOWNSTREAM"] q1 = obs1["OUTFLOW_DOWNSTREAM"] - assert np.allclose(q0, q1), f"downstream outflows not equal ('{name}')" + assert np.allclose(q0, q1), f"downstream outflows not equal ('{sim.name}')" d0 = obs0["DEPTH_UPSTREAM"] d1 = obs1["DEPTH_UPSTREAM"] - assert np.allclose(d0, d1), f"upstream depths are not equal ('{name}')" - - return + assert np.allclose(d0, d1), f"upstream depths are not equal ('{sim.name}')" -# - No need to change any code below @pytest.mark.parametrize( - "idx, exdir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, exdir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_models, idx, exdir) - - # run the test models - test.run_mf6( - Simulation( - exdir, +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_models, idx, ws) + test.run( + TestConfig( + name=name, + exes=targets, exfunc=eval_npointdepth, idxsim=idx, - ) + ), + ws ) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test models - for idx, exdir in enumerate(exdirs): - test.build_mf6_models(build_models, idx, exdir) - - sim = Simulation( - exdir, - exfunc=eval_npointdepth, - idxsim=idx, - ) - test.run_mf6(sim) - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_sfr_reorder.py b/autotest/test_gwf_sfr_reorder.py index 71fdfb352f6..22993904558 100644 --- a/autotest/test_gwf_sfr_reorder.py +++ b/autotest/test_gwf_sfr_reorder.py @@ -1,29 +1,13 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation - -sys.path.append("scripts") -from cross_section_functions import get_depths +from harness import TestHarness, TestConfig paktest = "sfr" - -ex = [ - "sfr_reorder", -] -exdirs = [os.path.join("temp", s) for s in ex] +ex = ["sfr_reorder"] # spatial discretization data nlay, nrow, ncol = 1, 1, 1 @@ -43,7 +27,7 @@ ustrf = 1.0 ndv = 0 -# + def build_model(idx, ws): # static model data @@ -221,14 +205,13 @@ def build_models(idx, base_ws): def eval_flows(sim): - idx = sim.idxsim - name = ex[idx] + name = sim.name print("evaluating flow results..." f"({name})") - obs_pth = os.path.join(exdirs[idx], f"{name}.sfr.obs.csv") + obs_pth = os.path.join(sim.simpath, f"{name}.sfr.obs.csv") obs0 = flopy.utils.Mf6Obs(obs_pth).get_data() - obs_pth = os.path.join(exdirs[idx], "mf6", f"{name}.sfr.obs.csv") + obs_pth = os.path.join(sim.simpath, "mf6", f"{name}.sfr.obs.csv") obs1 = flopy.utils.Mf6Obs(obs_pth).get_data() assert np.allclose(obs0["INFLOW"], obs1["INFLOW"]), "inflows are not equal" @@ -237,7 +220,7 @@ def eval_flows(sim): obs0["OUTFLOW"], obs1["OUTFLOW"] ), "outflows are not equal" - fpth = os.path.join(exdirs[idx], f"{name}.lst") + fpth = os.path.join(sim.simpath, f"{name}.lst") with open(fpth, "r") as f: lines = f.read().splitlines() @@ -257,51 +240,21 @@ def eval_flows(sim): order, actual ), "DAG did not correctly reorder reaches." - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, exdir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, exdir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_models, idx, exdir) - - # run the test models - test.run_mf6( - Simulation( - exdir, +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_models, idx, ws) + test.run( + TestConfig( + name=name, + exes=targets, exfunc=eval_flows, idxsim=idx, - ) + ), + ws ) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test models - for idx, exdir in enumerate(exdirs): - test.build_mf6_models(build_models, idx, exdir) - - sim = Simulation( - exdir, - exfunc=eval_flows, - idxsim=idx, - ) - test.run_mf6(sim) - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_sto01.py b/autotest/test_gwf_sto01.py index 08144c20bfe..11f83126a80 100644 --- a/autotest/test_gwf_sto01.py +++ b/autotest/test_gwf_sto01.py @@ -1,39 +1,17 @@ import os +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import running_on_CI, testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["gwf_sto01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) - cmppth = "mfnwt" tops = [0.0] - -ddir = "data" - -## run all examples on Travis -continuous_integration = [True for idx in range(len(exdirs))] - -# use default executable -replace_exe = None - -htol = [None for idx in range(len(exdirs))] +htol = [None for idx in range(len(ex))] dtol = 1e-3 budtol = 1e-2 - bud_lst = ["STO-SS_IN", "STO-SS_OUT", "STO-SY_IN", "STO-SY_OUT"] # static model data @@ -359,62 +337,17 @@ def eval_sto(sim): sim.success = True print(" " + msg) - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - - # determine if running on CI infrastructure - is_CI = running_on_CI() - r_exe = None - if not is_CI: - if replace_exe is not None: - r_exe = replace_exe - - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models_legacy(build_model, idx, dir) - - # run the test model - if is_CI and not continuous_integration[idx]: - return - test.run_mf6( - Simulation( - dir, exfunc=eval_sto, exe_dict=r_exe, htol=htol[idx], idxsim=idx - ) - ) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models_legacy(build_model, idx, dir) - sim = Simulation( - dir, - exfunc=eval_sto, - exe_dict=replace_exe, - htol=htol[idx], - idxsim=idx, - ) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run( + TestConfig( + name=name, exes=targets, exfunc=eval_sto, htol=htol[idx], idxsim=idx + ), + ws) diff --git a/autotest/test_gwf_sto02.py b/autotest/test_gwf_sto02.py index f4c471afb8f..9f6c0581b3e 100644 --- a/autotest/test_gwf_sto02.py +++ b/autotest/test_gwf_sto02.py @@ -5,36 +5,14 @@ import os +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["gwf_sto02a", "gwf_sto02b"] ncols = [1, 2] - -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" - nlay, nrow, = ( 1, 1, @@ -177,39 +155,21 @@ def eval_flow(sim): inc = mflist.get_incremental() print(inc) - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_flow, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_flow, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run( + TestConfig( + name=name, + exes=targets, + exfunc=eval_flow, + idxsim=idx, + ), + ws + ) diff --git a/autotest/test_gwf_sto03.py b/autotest/test_gwf_sto03.py index c90844c6070..a261dda2265 100644 --- a/autotest/test_gwf_sto03.py +++ b/autotest/test_gwf_sto03.py @@ -1,43 +1,21 @@ import os +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import running_on_CI, testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = [ "gwf_sto03a", "gwf_sto03b", ] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) - newton = ( False, True, ) - cmppth = "mf6" - -ddir = "data" - -## run all examples on Travis -continuous_integration = [True for idx in range(len(exdirs))] - -# use default executable -replace_exe = None - -htol = [None for idx in range(len(exdirs))] +htol = [None for idx in range(len(ex))] dtol = 1e-3 budtol = 1e-2 @@ -282,62 +260,18 @@ def eval_sto(sim): assert max_diff.sum() == 0.0, "simulated storage is not the same" - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - - # determine if running on CI infrastructure - is_CI = running_on_CI() - r_exe = None - if not is_CI: - if replace_exe is not None: - r_exe = replace_exe - - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - if is_CI and not continuous_integration[idx]: - return - test.run_mf6( - Simulation( - dir, exfunc=eval_sto, exe_dict=r_exe, htol=htol[idx], idxsim=idx - ) +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run( + TestConfig( + name=name, exes=targets, exfunc=eval_sto, htol=htol[idx], idxsim=idx + ), + ws ) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation( - dir, - exfunc=eval_sto, - exe_dict=replace_exe, - htol=htol[idx], - idxsim=idx, - ) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_sto_tvs01.py b/autotest/test_gwf_sto_tvs01.py index 5f169bc6219..df926a4c11d 100644 --- a/autotest/test_gwf_sto_tvs01.py +++ b/autotest/test_gwf_sto_tvs01.py @@ -1,35 +1,12 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation - -ex = [ - "tvs01", -] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" +from harness import TestHarness, TestConfig + +ex = ["tvs01"] def build_model(idx, dir): @@ -188,8 +165,7 @@ def build_model(idx, dir): def eval_model(sim): print("evaluating model...") - name = ex[sim.idxsim] - gwfname = "gwf_" + name + gwfname = "gwf_" + sim.name # head fpth = os.path.join(sim.simpath, f"{gwfname}.hds") @@ -228,39 +204,13 @@ def eval_model(sim): # comment when done testing # assert False - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_model, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_model, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_model, idxsim=0), ws) diff --git a/autotest/test_gwf_ts_lak01.py b/autotest/test_gwf_ts_lak01.py index e9fea2f9c8d..1f330abf0f5 100644 --- a/autotest/test_gwf_ts_lak01.py +++ b/autotest/test_gwf_ts_lak01.py @@ -1,41 +1,15 @@ import os +import flopy import numpy as np import pytest +from flopy.utils.compare import eval_bud_diff -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig paktest = "lak" budtol = 1e-2 - ex = ["ts_lak01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" - -# run all examples on Travis -continuous_integration = [True for idx in range(len(exdirs))] - -# set replace_exe to None to use default executable -replace_exe = None # static model data # spatial discretization @@ -355,7 +329,6 @@ def build_model(idx, dir): def eval_budget(sim): print("evaluating budgets...") - from budget_file_compare import eval_bud_diff # get ia/ja from binary grid file fname = f"{os.path.basename(sim.name)}.dis.grb" @@ -378,44 +351,14 @@ def eval_budget(sim): fpth = os.path.join(sim.simpath, fname) eval_bud_diff(fpth, cobj0, cobj1, ia, dtol=0.1) - return - - -# - No need to change any code below - +@pytest.mark.slow @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_budget, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_budget, idxsim=idx) - test.run_mf6(sim) - return - - -# use python testmf6_drn_ddrn01.py -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_budget, idxsim=idx), ws) diff --git a/autotest/test_gwf_ts_maw01.py b/autotest/test_gwf_ts_maw01.py index 0eb277a98af..eb75da05194 100644 --- a/autotest/test_gwf_ts_maw01.py +++ b/autotest/test_gwf_ts_maw01.py @@ -1,30 +1,14 @@ import os +import flopy import numpy as np import pytest +from flopy.utils.compare import eval_bud_diff -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig paktest = "maw" ex = [f"ts_{paktest}01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) - -# run all examples on Travis -continuous_integration = [True for idx in range(len(exdirs))] - -# set replace_exe to None to use default executable -replace_exe = None def get_model(ws, name, timeseries=False): @@ -431,8 +415,6 @@ def build_model(idx, dir): def eval_model(sim): print("evaluating model budgets...") - from budget_file_compare import eval_bud_diff - # get ia/ja from binary grid file fname = f"{os.path.basename(sim.name)}.dis.grb" fpth = os.path.join(sim.simpath, fname) @@ -469,43 +451,13 @@ def eval_model(sim): fpth = os.path.join(sim.simpath, fname) eval_bud_diff(fpth, cobj0, cobj1) - return - - -# - No need to change any code below - @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_model, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_model, idxsim=idx) - test.run_mf6(sim) - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_model, idxsim=idx), ws) diff --git a/autotest/test_gwf_ts_sfr01.py b/autotest/test_gwf_ts_sfr01.py index faa6b60b334..b1ec840f227 100644 --- a/autotest/test_gwf_ts_sfr01.py +++ b/autotest/test_gwf_ts_sfr01.py @@ -1,30 +1,14 @@ import os +import flopy import numpy as np import pytest +from flopy.utils.compare import eval_bud_diff -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig paktest = "sfr" ex = ["ts_sfr01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) - -# run all examples on Travis -continuous_integration = [True for idx in range(len(exdirs))] - -# set replace_exe to None to use default executable -replace_exe = None def get_model(ws, name, timeseries=False): @@ -546,7 +530,6 @@ def build_model(idx, dir): def eval_model(sim): print("evaluating model budgets...") - from budget_file_compare import eval_bud_diff # get ia/ja from binary grid file fname = f"{os.path.basename(sim.name)}.dis.grb" @@ -610,43 +593,13 @@ def eval_model(sim): check = np.array([0.0, 0.0, -2.5e-2, 0.0, -2.0e-2, 0.0]) assert np.allclose(v0, check), "FROM-MVR failed" - return - - -# - No need to change any code below - @pytest.mark.parametrize( - "idx, exdir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, exdir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, exdir) - - # run the test model - test.run_mf6(Simulation(exdir, exfunc=eval_model, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, exdir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, exdir) - sim = Simulation(exdir, exfunc=eval_model, idxsim=idx) - test.run_mf6(sim) - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_model, idxsim=idx), ws) diff --git a/autotest/test_gwf_ts_sfr02.py b/autotest/test_gwf_ts_sfr02.py index 6cf9220424a..a417f86f8c1 100644 --- a/autotest/test_gwf_ts_sfr02.py +++ b/autotest/test_gwf_ts_sfr02.py @@ -1,30 +1,14 @@ import os +import flopy import numpy as np import pytest +from flopy.utils.compare import eval_bud_diff -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig paktest = "sfr" ex = ["ts_sfr02"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) - -# run all examples on Travis -continuous_integration = [True for idx in range(len(exdirs))] - -# set replace_exe to None to use default executable -replace_exe = None def get_model(ws, name, timeseries=False): @@ -537,7 +521,6 @@ def build_model(idx, dir): def eval_model(sim): print("evaluating model budgets...") - from budget_file_compare import eval_bud_diff # get ia/ja from binary grid file fname = f"{os.path.basename(sim.name)}.dis.grb" @@ -616,43 +599,13 @@ def eval_model(sim): check = np.array([-2.5e-2, 0.0, 0.0, 0.0, -2.0e-2, 0.0]) assert np.allclose(v0, check), "TO-MVR failed" - return - - -# - No need to change any code below - @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_model, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_model, idxsim=idx) - test.run_mf6(sim) - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_model, idxsim=idx), ws) diff --git a/autotest/test_gwf_ts_uzf01.py b/autotest/test_gwf_ts_uzf01.py index 6714a31f637..c7364e64e5c 100644 --- a/autotest/test_gwf_ts_uzf01.py +++ b/autotest/test_gwf_ts_uzf01.py @@ -1,30 +1,14 @@ import os +import flopy import numpy as np import pytest +from flopy.utils.compare import eval_bud_diff -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig paktest = "uzf" ex = ["ts_uzf01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) - -# run all examples on Travis -continuous_integration = [True for idx in range(len(exdirs))] - -# set replace_exe to None to use default executable -replace_exe = None def get_model(ws, name, timeseries=False): @@ -664,7 +648,6 @@ def build_model(idx, dir): def eval_model(sim): print("evaluating model budgets...") - from budget_file_compare import eval_bud_diff # get ia/ja from binary grid file fname = f"{os.path.basename(sim.name)}.dis.grb" @@ -702,43 +685,13 @@ def eval_model(sim): fpth = os.path.join(sim.simpath, fname) eval_bud_diff(fpth, cobj0, cobj1) - return - - -# - No need to change any code below - @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_model, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_model, idxsim=idx) - test.run_mf6(sim) - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_model, idxsim=idx), ws) diff --git a/autotest/test_gwf_utl01_binaryinput.py b/autotest/test_gwf_utl01_binaryinput.py index 0bf84dd7db6..0066976f088 100644 --- a/autotest/test_gwf_utl01_binaryinput.py +++ b/autotest/test_gwf_utl01_binaryinput.py @@ -4,25 +4,13 @@ import os +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["binary01", "binary02"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" def build_model(idx, dir): @@ -88,7 +76,7 @@ def build_model(idx, dir): # write top to a binary file text = "TOP" fname = "top.bin" - pth = os.path.join(exdirs[idx], fname) + pth = os.path.join(dir, fname) f = open(pth, "wb") header = flopy.utils.BinaryHeader.create( bintype="HEAD", @@ -123,7 +111,7 @@ def build_model(idx, dir): for k in range(nlay): text = f"BOTM_L{k + 1}" fname = f"botm.l{k + 1:02d}.bin" - pth = os.path.join(exdirs[idx], fname) + pth = os.path.join(dir, fname) f = open(pth, "wb") header = flopy.utils.BinaryHeader.create( bintype="HEAD", @@ -155,7 +143,7 @@ def build_model(idx, dir): ) elif idx == 1: fname = "botm.bin" - pth = os.path.join(exdirs[idx], fname) + pth = os.path.join(dir, fname) f = open(pth, "wb") tarr = np.ones((nlay, nrow, ncol), dtype=np.float64) for k in range(nlay): @@ -189,7 +177,7 @@ def build_model(idx, dir): for k in range(nlay): text = f"IDOMAIN_L{k + 1}" fname = f"idomain.l{k + 1:02d}.bin" - pth = os.path.join(exdirs[idx], fname) + pth = os.path.join(dir, fname) f = open(pth, "wb") header = flopy.utils.BinaryHeader.create( bintype="HEAD", @@ -221,7 +209,7 @@ def build_model(idx, dir): ) elif idx == 1: fname = "idomain.bin" - pth = os.path.join(exdirs[idx], fname) + pth = os.path.join(dir, fname) f = open(pth, "wb") header = flopy.utils.BinaryHeader.create( bintype="HEAD", @@ -270,7 +258,7 @@ def build_model(idx, dir): for k in range(nlay): text = f"IC_L{k + 1}" fname = f"ic.strt_l{k + 1:02d}.bin" - pth = os.path.join(exdirs[idx], fname) + pth = os.path.join(dir, fname) f = open(pth, "wb") header = flopy.utils.BinaryHeader.create( bintype="HEAD", @@ -302,7 +290,7 @@ def build_model(idx, dir): ) elif idx == 1: fname = "ic.strt.bin" - pth = os.path.join(exdirs[idx], fname) + pth = os.path.join(dir, fname) f = open(pth, "wb") header = flopy.utils.BinaryHeader.create( bintype="HEAD", @@ -339,7 +327,7 @@ def build_model(idx, dir): icelltype = [] for k in range(nlay): fname = f"npf.icelltype.l{k + 1}.bin" - pth = os.path.join(exdirs[idx], fname) + pth = os.path.join(dir, fname) f = open(pth, "wb") header = flopy.utils.BinaryHeader.create( bintype="head", @@ -372,7 +360,7 @@ def build_model(idx, dir): ) elif idx == 1: fname = "npf.icelltype.bin" - pth = os.path.join(exdirs[idx], fname) + pth = os.path.join(dir, fname) f = open(pth, "wb") header = flopy.utils.BinaryHeader.create( bintype="head", @@ -439,39 +427,12 @@ def build_model(idx, dir): return sim, None -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets), ws) diff --git a/autotest/test_gwf_utl02_timeseries.py b/autotest/test_gwf_utl02_timeseries.py index 573c2989f0e..a2e9eab5366 100644 --- a/autotest/test_gwf_utl02_timeseries.py +++ b/autotest/test_gwf_utl02_timeseries.py @@ -1,24 +1,9 @@ -import os - -import numpy as np +import flopy import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["ts01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" def build_model(idx, dir): @@ -163,39 +148,12 @@ def build_model(idx, dir): return sim, None -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets), ws) diff --git a/autotest/test_gwf_utl03_obs01.py b/autotest/test_gwf_utl03_obs01.py index 4f5944833a6..210908ebb13 100644 --- a/autotest/test_gwf_utl03_obs01.py +++ b/autotest/test_gwf_utl03_obs01.py @@ -1,25 +1,12 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["utl03_obs"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" # temporal discretization nper = 2 @@ -61,12 +48,12 @@ hclose, rclose, relax = 1e-6, 0.01, 1.0 -def build_mf6(idx, ws, binaryobs=True): +def build_mf6(idx, ws, exe, binaryobs=True): name = ex[idx] # build MODFLOW 6 files sim = flopy.mf6.MFSimulation( - sim_name=name, version="mf6", exe_name="mf6", sim_ws=ws + sim_name=name, version="mf6", exe_name=exe, sim_ws=ws ) # create tdis package flopy.mf6.ModflowTdis( @@ -150,21 +137,26 @@ def build_mf6(idx, ws, binaryobs=True): return sim -def build_model(idx, dir): +def build_model(idx, dir, exe): ws = dir # build mf6 with ascii observation output - sim = build_mf6(idx, ws, binaryobs=False) + sim = build_mf6(idx, ws, exe=exe, binaryobs=False) # build mf6 with binary observation output wsc = os.path.join(ws, "mf6") - mc = build_mf6(idx, wsc, binaryobs=True) + mc = build_mf6(idx, wsc, exe=exe, binaryobs=True) + + sim.write_simulation() + mc.write_simulation() + hack_binary_obs(idx, dir) return sim, mc -def build_models(): - for idx, dir in enumerate(exdirs): - sim, mc = build_model(idx, dir) + +def build_models(dir, exe): + for idx, name in enumerate(ex): + sim, mc = build_model(idx, dir, exe) sim.write_simulation() mc.write_simulation() hack_binary_obs(idx, dir) @@ -224,41 +216,14 @@ def eval_obs(sim): ) assert np.allclose(d0[name], d1[name], rtol=1e-5), msg - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - build_models() - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_obs)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - build_models() - - # run the test model - for dir in exdirs: - sim = Simulation(dir, exfunc=eval_obs) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + mf6 = targets["mf6"] + test = TestHarness() + build_models(ws, mf6) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_obs), ws) diff --git a/autotest/test_gwf_utl04_auxmult.py b/autotest/test_gwf_utl04_auxmult.py index 9c925f36336..4c21b57e58e 100644 --- a/autotest/test_gwf_utl04_auxmult.py +++ b/autotest/test_gwf_utl04_auxmult.py @@ -6,25 +6,13 @@ import os +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["auxmult01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" def build_model(idx, dir): @@ -191,39 +179,13 @@ def eval_model(sim): # assert False - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_model, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_model, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_model), ws) diff --git a/autotest/test_gwf_utl05_budparse.py b/autotest/test_gwf_utl05_budparse.py index d62d7f74ed2..9437faeae05 100644 --- a/autotest/test_gwf_utl05_budparse.py +++ b/autotest/test_gwf_utl05_budparse.py @@ -5,36 +5,16 @@ import os +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["gwf_utl05"] laytyp = [1] ss = [1.0e-10] sy = [0.1] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" nlay, nrow, ncol = 1, 1, 1 @@ -164,8 +144,7 @@ def build_model(idx, dir): def eval_flow(sim): print("evaluating flow...") - name = ex[sim.idxsim] - gwfname = "gwf_" + name + gwfname = "gwf_" + sim.name # This will fail if budget numbers cannot be read fpth = os.path.join(sim.simpath, f"{gwfname}.lst") @@ -180,36 +159,12 @@ def eval_flow(sim): assert np.allclose(inc["WEL_OUT"], 0.0) -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_flow, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_flow, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_flow, idxsim=0), ws) diff --git a/autotest/test_gwf_utl06_tas.py b/autotest/test_gwf_utl06_tas.py index 0f5b3bd8e05..6614b7ee7b1 100644 --- a/autotest/test_gwf_utl06_tas.py +++ b/autotest/test_gwf_utl06_tas.py @@ -6,19 +6,11 @@ import os +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = [ "utl06_tas_a", @@ -26,9 +18,6 @@ "utl06_tas_c", "utl06_tas_d", ] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) nlay, nrow, ncol = 3, 5, 5 idomain_lay0 = [ @@ -375,42 +364,13 @@ def eval_transport(sim): qa = [a * rate * frac for a, rate in zip(area, id2a)] assert np.allclose(q, qa), f"{q} /=\n {qa}" - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=idx), ws) diff --git a/autotest/test_gwf_uzf01.py b/autotest/test_gwf_uzf01.py index 1fcbc24890c..1caf54b9377 100644 --- a/autotest/test_gwf_uzf01.py +++ b/autotest/test_gwf_uzf01.py @@ -6,33 +6,13 @@ import os +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["gwf_uzf01a"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" nlay, nrow, ncol = 100, 1, 1 @@ -236,8 +216,8 @@ def build_model(idx, exdir): def eval_flow(sim): print("evaluating flow...") - name = ex[sim.idxsim] - ws = exdirs[sim.idxsim] + name = sim.name + ws = sim.simpath # check binary grid file fname = os.path.join(ws, name + ".dis.grb") @@ -281,41 +261,13 @@ def eval_flow(sim): "data in the cell-by-cell file." ) - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, exdir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, exdir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, exdir) - - # run the test model - test.run_mf6(Simulation(exdir, exfunc=eval_flow, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, exdir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, exdir) - sim = Simulation(exdir, exfunc=eval_flow, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_flow, idxsim=idx), ws) diff --git a/autotest/test_gwf_uzf02.py b/autotest/test_gwf_uzf02.py index 0e0eed7dc40..de24cafcdd4 100644 --- a/autotest/test_gwf_uzf02.py +++ b/autotest/test_gwf_uzf02.py @@ -5,33 +5,13 @@ import os +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["gwf_uzf02a"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" nlay, nrow, ncol = 1, 1, 1 @@ -248,9 +228,6 @@ def build_model(idx, dir): def make_plot(sim, obsvals): print("making plots...") - name = ex[sim.idxsim] - ws = exdirs[sim.idxsim] - # shows curves for times 2.5, 7.5, 12.6, 17.7 # which are indices 24, 74, 125, and -1 idx = [24, 74, 125, -1] @@ -276,17 +253,15 @@ def make_plot(sim, obsvals): plt.legend() fname = "fig-xsect.pdf" - fname = os.path.join(ws, fname) + fname = os.path.join(sim.simpath, fname) plt.savefig(fname, bbox_inches="tight") - return - def eval_flow(sim): print("evaluating flow...") - name = ex[sim.idxsim] - ws = exdirs[sim.idxsim] + name = sim.name + ws = sim.simpath # check binary grid file fname = os.path.join(ws, name + ".dis.grb") @@ -330,41 +305,14 @@ def eval_flow(sim): assert False, f'could not load data from "{fpth}"' if False: make_plot(sim, obsvals) - return -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_flow, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_flow, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_flow, idxsim=0), ws) diff --git a/autotest/test_gwf_uzf03.py b/autotest/test_gwf_uzf03.py index cbcad1e6dbf..858c8172e25 100644 --- a/autotest/test_gwf_uzf03.py +++ b/autotest/test_gwf_uzf03.py @@ -6,38 +6,17 @@ import os +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["gwf_uzf03a"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" nlay, nrow, ncol = 15, 1, 1 def build_model(idx, dir): - perlen = [17.7] nper = len(perlen) nstp = [177] @@ -250,9 +229,6 @@ def build_model(idx, dir): def make_plot(sim, obsvals): print("making plots...") - name = ex[sim.idxsim] - ws = exdirs[sim.idxsim] - # shows curves for times 2.5, 7.5, 12.6, 17.7 # which are indices 24, 74, 125, and -1 idx = [24, 74, 125, -1] @@ -277,17 +253,15 @@ def make_plot(sim, obsvals): plt.legend() fname = "fig-xsect.pdf" - fname = os.path.join(ws, fname) + fname = os.path.join(sim.simpath, fname) plt.savefig(fname, bbox_inches="tight") - return - def eval_flow(sim): print("evaluating flow...") - name = ex[sim.idxsim] - ws = exdirs[sim.idxsim] + name = sim.name + ws = sim.simpath # check binary grid file fname = os.path.join(ws, name + ".dis.grb") @@ -331,41 +305,14 @@ def eval_flow(sim): assert False, f'could not load data from "{fpth}"' if False: make_plot(sim, obsvals) - return -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_flow, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_flow, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_flow, idxsim=0), ws) diff --git a/autotest/test_gwf_uzf04.py b/autotest/test_gwf_uzf04.py index 05ea7f8025d..0facf6d3940 100644 --- a/autotest/test_gwf_uzf04.py +++ b/autotest/test_gwf_uzf04.py @@ -11,35 +11,14 @@ import os +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["gwf_uzf04a"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" nlay, nrow, ncol = 1, 1, 1 - thts = 0.30 # saturated water content thtr = 0.05 # residual water content thti = 0.10 # initial water content @@ -239,8 +218,8 @@ def build_model(idx, dir): def eval_flow(sim): print("evaluating flow...") - name = ex[sim.idxsim] - ws = exdirs[sim.idxsim] + name = sim.name + ws = sim.simpath fname = os.path.join(ws, f"{name}.uzf.bin") wobj = flopy.utils.HeadFile(fname, text="WATER-CONTENT") @@ -277,41 +256,13 @@ def eval_flow(sim): vw, volume_mobile_sim ), "Simulated mobile water volume in aux does not match known result" - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_flow, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_flow, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_flow, idxsim=idx), ws) diff --git a/autotest/test_gwf_uzf05.py b/autotest/test_gwf_uzf05.py index 7258a5a03cf..798a45488c4 100644 --- a/autotest/test_gwf_uzf05.py +++ b/autotest/test_gwf_uzf05.py @@ -10,30 +10,11 @@ import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +import flopy + +from harness import TestHarness, TestConfig ex = ["gwf_uzf05a"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" nlay, nrow, ncol = 3, 1, 1 thts = 0.30 # saturated water content @@ -237,8 +218,8 @@ def build_model(idx, dir): def eval_flow(sim): print("evaluating flow...") - name = ex[sim.idxsim] - ws = exdirs[sim.idxsim] + name = sim.name + ws = sim.simpath fname = os.path.join(ws, f"{name}.uzf.bin") wobj = flopy.utils.HeadFile(fname, text="WATER-CONTENT") @@ -258,41 +239,13 @@ def eval_flow(sim): assert node2 == 1, "GWF node should be 1" assert np.isclose(q, -4.), "Flow from UZF to node 1 should be -4." - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_flow, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_flow, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_flow, idxsim=idx), ws) diff --git a/autotest/test_gwf_uzf_gwet.py b/autotest/test_gwf_uzf_gwet.py index 171d984a903..456a64b7d45 100644 --- a/autotest/test_gwf_uzf_gwet.py +++ b/autotest/test_gwf_uzf_gwet.py @@ -1,34 +1,14 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["uzf_3lay"] -exdirs = [] iuz_cell_dict = {} cell_iuz_dict = {} -for s in ex: - exdirs.append(os.path.join("temp", s)) def build_model(idx, dir): @@ -280,8 +260,7 @@ def build_model(idx, dir): def eval_model(sim): print("evaluating model...") - name = ex[sim.idxsim] - ws = exdirs[sim.idxsim] + ws = sim.simpath sim = flopy.mf6.MFSimulation.load(sim_ws=ws) fpth = os.path.join(ws, "uzf_3lay.hds") @@ -391,36 +370,11 @@ def eval_model(sim): print("Finished running checks") -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", ex ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_model, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_model, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_model, idxsim=0), ws) diff --git a/autotest/test_gwf_uzf_surfdep.py b/autotest/test_gwf_uzf_surfdep.py index b9d101fd682..18e249dc382 100644 --- a/autotest/test_gwf_uzf_surfdep.py +++ b/autotest/test_gwf_uzf_surfdep.py @@ -1,40 +1,13 @@ -import os -import shutil -import subprocess -import sys - -import numpy as np -import pytest - -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -import targets - -mf6_exe = os.path.abspath(targets.target_dict["mf6"]) +import flopy + + testname = "uzf_3lay_srfdchk" -testdir = os.path.join("temp", testname) -os.makedirs(testdir, exist_ok=True) -everything_was_successful = True iuz_cell_dict = {} cell_iuz_dict = {} -def build_model(): +def build_model(dir, exe): nlay, nrow, ncol = 3, 1, 10 nper = 1 @@ -61,9 +34,9 @@ def build_model(): name = testname # build MODFLOW 6 files - ws = testdir + ws = dir sim = flopy.mf6.MFSimulation( - sim_name=name, version="mf6", exe_name=mf6_exe, sim_ws=ws + sim_name=name, version="mf6", exe_name=exe, sim_ws=ws ) # create tdis package @@ -213,15 +186,15 @@ def build_model(): return sim -# - No need to change any code below -def test_mf6model(): +def test_mf6model(function_tmpdir, targets): # build and run the test model - sim = build_model() + mf6 = targets.mf6 + sim = build_model(str(function_tmpdir), mf6) sim.write_simulation() sim.run_simulation() # ensure that the error msg is contained in the mfsim.lst file - f = open(os.path.join(testdir, "mfsim.lst"), "r") + f = open(str(function_tmpdir / "mfsim.lst"), "r") lines = f.readlines() error_count = 0 expected_msg = False @@ -236,20 +209,3 @@ def test_mf6model(): print("Finished running surfdep check") - shutil.rmtree(testdir, ignore_errors=True) - - return - - -def main(): - test_mf6model() - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_uzf_wc_output.py b/autotest/test_gwf_uzf_wc_output.py index 1404ca4b21f..459db7212c0 100644 --- a/autotest/test_gwf_uzf_wc_output.py +++ b/autotest/test_gwf_uzf_wc_output.py @@ -1,33 +1,15 @@ import os +import flopy +import flopy.utils.binaryfile as bf import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -import flopy.utils.binaryfile as bf - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig include_NWT = False ex = ["uzf_3lay_wc_chk"] -exdirs = [os.path.join("temp", name) for name in ex] iuz_cell_dict = {} cell_iuz_dict = {} @@ -470,9 +452,8 @@ def build_model(idx, ws): def eval_model(sim): print("evaluating model...") - idx = sim.idxsim - name = ex[idx] - ws = os.path.join("temp", name) + name = sim.name + ws = sim.simpath # Get the MF6 heads fpth = os.path.join(ws, "uzf_3lay_wc_chk.hds") @@ -560,39 +541,20 @@ def eval_model(sim): print("Finished running checks") -# - No need to change any code below @pytest.mark.parametrize( - "idx, exdir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, exdir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, exdir) - - # run the test models - test.run_mf6( - Simulation( - exdir, +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run( + TestConfig( + name=name, + exes=targets, exfunc=eval_model, - idxsim=idx, - ) + idxsim=0, + ), + ws ) - return - - -def main(): - for idx, exdir in enumerate(exdirs): - test_mf6model(idx, exdir) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwf_vsc01.py b/autotest/test_gwf_vsc01.py index 0c547db2e77..b635d2c166d 100644 --- a/autotest/test_gwf_vsc01.py +++ b/autotest/test_gwf_vsc01.py @@ -14,24 +14,14 @@ import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) +import flopy -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig hyd_cond = [1205.49396942506, 864.0] # Hydraulic conductivity (m/d) ex = ["no-vsc01-bnd", "vsc01-bnd", "no-vsc01-k"] viscosity_on = [False, True, False] hydraulic_conductivity = [hyd_cond[0], hyd_cond[1], hyd_cond[1]] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) # Model units @@ -287,7 +277,7 @@ def eval_results(sim): # Ensure latest simulated value hasn't changed from stored answer assert np.allclose( sim_val_1, stored_ans, atol=1e-4 - ), "Flow in the " + exdirs[ + ), "Flow in the " + ex[ 0 ] + " test problem (doesn't simulate " "viscosity) has changed,\n should be " + str( stored_ans @@ -302,7 +292,7 @@ def eval_results(sim): # Ensure latest simulated value hasn't changed from stored answer assert np.allclose( sim_val_2, stored_ans, atol=1e-4 - ), "Flow in the " + exdirs[ + ), "Flow in the " + ex[ 1 ] + " test problem (simulates " "viscosity) has changed,\n should be " + str( stored_ans @@ -317,43 +307,20 @@ def eval_results(sim): # Ensure the flow leaving model 3 is less than what leaves model 2 assert abs(stored_ans) > abs(sim_val_3), ( "Exit flow from model " - + exdirs[1] + + ex[1] + " should be greater than flow exiting " - + exdirs[2] + + ex[2] + ", but it is not." ) # - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_results, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_results, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_results, idxsim=idx), ws) diff --git a/autotest/test_gwf_vsc02.py b/autotest/test_gwf_vsc02.py index 2e6039d5116..9f0b41fdf44 100644 --- a/autotest/test_gwf_vsc02.py +++ b/autotest/test_gwf_vsc02.py @@ -15,26 +15,15 @@ import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -# Import common functionality -from framework import testing_framework -from simulation import Simulation +import flopy + +from harness import TestHarness, TestConfig # Setup scenario input hyd_cond = [1205.49396942506, 864.0] # Hydraulic conductivity (m/d) ex = ["no-vsc02-bnd", "vsc02-bnd", "no-vsc02-k"] viscosity_on = [False, True, False] hydraulic_conductivity = [hyd_cond[0], hyd_cond[1], hyd_cond[1]] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) # Model units @@ -291,7 +280,7 @@ def eval_results(sim): # Ensure latest simulated value hasn't changed from stored answer assert np.allclose( sim_val_1, stored_ans, atol=1e-4 - ), "Flow in the " + exdirs[ + ), "Flow in the " + ex[ 0 ] + " test problem (doesn't simulate " "viscosity) has changed,\n should be " + str( stored_ans @@ -306,7 +295,7 @@ def eval_results(sim): # Ensure latest simulated value hasn't changed from stored answer assert np.allclose( sim_val_2, stored_ans, atol=1e-4 - ), "Flow in the " + exdirs[ + ), "Flow in the " + ex[ 1 ] + " test problem (simulates " "viscosity) has changed,\n should be " + str( stored_ans @@ -321,43 +310,19 @@ def eval_results(sim): # Ensure the flow leaving model 3 is less than what leaves model 2 assert abs(stored_ans) > abs(sim_val_3), ( "Exit flow from model " - + exdirs[1] + + ex[1] + " should be greater than flow existing " - + exdirs[2] + + ex[2] + ", but it is not." ) -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_results, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_results, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_results, idxsim=idx), ws) diff --git a/autotest/test_gwf_vsc03_sfr.py b/autotest/test_gwf_vsc03_sfr.py index a3c79f0620b..97efc113e01 100644 --- a/autotest/test_gwf_vsc03_sfr.py +++ b/autotest/test_gwf_vsc03_sfr.py @@ -15,22 +15,12 @@ import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) +import flopy -from framework import testing_framework -from simulation import Simulation +from harness import TestConfig, TestHarness ex = ["no-vsc-sfr01", "vsc-sfr01"] viscosity_on = [False, True] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) # Equation for determining land surface elevation with a stream running down the middle def topElev_sfrCentered(x, y): @@ -541,36 +531,12 @@ def eval_results(sim): ) -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_results, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_results, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_results, idxsim=idx), ws) diff --git a/autotest/test_gwf_vsc04_lak.py b/autotest/test_gwf_vsc04_lak.py index 54757eca6e5..c59865e989f 100644 --- a/autotest/test_gwf_vsc04_lak.py +++ b/autotest/test_gwf_vsc04_lak.py @@ -14,27 +14,15 @@ # import os -import sys +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["no-vsc04-lak", "vsc04-lak"] viscosity_on = [False, True] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) # Model units length_units = "m" @@ -174,11 +162,10 @@ # -def build_model(idx, dir): +def build_model(idx, ws): global lak_lkup_dict # Base simulation and model name and workspace - ws = dir name = ex[idx] print("Building model...{}".format(name)) @@ -787,36 +774,12 @@ def eval_results(sim): ) -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_results, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_results, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_results, idxsim=idx), ws) diff --git a/autotest/test_gwf_vsc05_hfb.py b/autotest/test_gwf_vsc05_hfb.py index 6846226fd78..148aa53f5b8 100644 --- a/autotest/test_gwf_vsc05_hfb.py +++ b/autotest/test_gwf_vsc05_hfb.py @@ -26,24 +26,14 @@ import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) +import flopy -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig hyd_cond = [1205.49396942506, 864.0] # Hydraulic conductivity (m/d) ex = ["no-vsc05-hfb", "vsc05-hfb", "no-vsc05-k"] viscosity_on = [False, True, False] hydraulic_conductivity = [hyd_cond[0], hyd_cond[1], hyd_cond[1]] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) # Model units @@ -350,7 +340,7 @@ def eval_results(sim): no_vsc_bud_last[:, 2], stored_ans[:, 2], atol=1e-3 ), ( "Flow in models " - + exdirs[0] + + ex[0] + " and the established answer should be approximately " "equal, but are not." ) @@ -362,7 +352,7 @@ def eval_results(sim): with_vsc_bud_last[:, 2], stored_ans[:, 2], atol=1e-3 ), ( "Flow in models " - + exdirs[1] + + ex[1] + " and the established answer should be approximately " "equal, but are not." ) @@ -375,41 +365,18 @@ def eval_results(sim): assert np.less(no_vsc_low_k_bud_last[:, 2], stored_ans[:, 2]).all(), ( "Exit flow from model the established answer " "should be greater than flow existing " - + exdirs[2] + + ex[2] + ", but it is not." ) # - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_results, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_results, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_results, idxsim=idx), ws) diff --git a/autotest/test_gwf_wel01.py b/autotest/test_gwf_wel01.py index c6923112ccc..06797fbdaac 100644 --- a/autotest/test_gwf_wel01.py +++ b/autotest/test_gwf_wel01.py @@ -5,33 +5,13 @@ """ import os +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["wel01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" # set static data nper = 1 @@ -201,39 +181,13 @@ def eval_obs(sim): errmsg += f"{a1} /= {a2}" assert np.allclose(a1, a2), errmsg - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_obs, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_obs, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_obs, idxsim=idx), ws) diff --git a/autotest/test_gwf_zb01.py b/autotest/test_gwf_zb01.py index 36fa5c8ca83..c496f0f9d3f 100644 --- a/autotest/test_gwf_zb01.py +++ b/autotest/test_gwf_zb01.py @@ -1,37 +1,15 @@ import os +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -import targets -from framework import running_on_CI, testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["zbud6_zb01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) - -ddir = "data" - -## run all examples on Travis -continuous_integration = [True for idx in range(len(exdirs))] - -# set replace_exe to None to use default executable -replace_exe = None - -htol = [None for idx in range(len(exdirs))] +htol = [None for idx in range(len(ex))] dtol = 1e-3 budtol = 1e-2 - bud_lst = [ "STO-SS_IN", "STO-SS_OUT", @@ -132,13 +110,13 @@ # variant SUB package problem 3 -def build_model(idx, dir): +def build_model(idx, dir, exe): name = ex[idx] # build MODFLOW 6 files ws = dir sim = flopy.mf6.MFSimulation( - sim_name=name, version="mf6", exe_name="mf6", sim_ws=ws + sim_name=name, version="mf6", exe_name=exe, sim_ws=ws ) # create tdis package tdis = flopy.mf6.ModflowTdis( @@ -238,8 +216,7 @@ def build_model(idx, dir): return sim, None -def eval_zb6(sim): - +def eval_zb6(sim, exe): print("evaluating zonebudget...") # build zonebudget files @@ -267,21 +244,18 @@ def eval_zb6(sim): f.close() # run zonebudget - zbexe = os.path.abspath(targets.target_dict["zbud6"]) success, buff = flopy.run_model( - zbexe, + exe, "zonebudget.nam", model_ws=sim.simpath, silent=False, report=True, ) if success: - print(f"successfully ran...{os.path.basename(zbexe)}") sim.success = True else: sim.success = False - msg = f"could not run...{zbexe}" - assert success, msg + assert success # read data from csv file fpth = os.path.join(sim.simpath, "zonebudget.csv") @@ -414,62 +388,20 @@ def eval_zb6(sim): sim.success = True print(" " + msg) - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - - # determine if running on CI infrastructure - is_CI = running_on_CI() - r_exe = None - if not is_CI: - if replace_exe is not None: - r_exe = replace_exe - - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models_legacy(build_model, idx, dir) - - # run the test model - if is_CI and not continuous_integration[idx]: - return - test.run_mf6( - Simulation( - dir, exfunc=eval_zb6, exe_dict=r_exe, htol=htol[idx], idxsim=idx - ) +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + mf6 = targets.mf6 + zb6 = targets.zbud6 + test = TestHarness() + test.build(lambda i, w: build_model(i, w, mf6), idx, ws) + test.run( + TestConfig( + name=name, exes=targets, exfunc=lambda s: eval_zb6(s, zb6), htol=htol[idx], idxsim=idx + ), + ws ) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models_legacy(build_model, idx, dir) - sim = Simulation( - dir, - exfunc=eval_zb6, - exe_dict=replace_exe, - htol=htol[idx], - idxsim=idx, - ) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() diff --git a/autotest/test_gwfgwf_lgr.py b/autotest/test_gwfgwf_lgr.py index 74b94a63d69..10b08bfd0ed 100644 --- a/autotest/test_gwfgwf_lgr.py +++ b/autotest/test_gwfgwf_lgr.py @@ -32,27 +32,15 @@ """ import os +import flopy import numpy as np import pytest - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - from flopy.utils.lgrutil import Lgr -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["gwfgwf_lgr_classic", "gwfgwf_lgr_ifmod"] ifmod = [False, True] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) parent_name = "parent" child_name = "child" @@ -287,41 +275,13 @@ def eval_heads(sim): errmsg = f"min or max residual too large {res.min()} {res.max()}" assert np.allclose(res, 0.0, atol=1.0e-6), errmsg - return - @pytest.mark.parametrize( - "idx, exdir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -@pytest.mark.developmode -def test_mf6model(idx, exdir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, exdir) - - # run the test model - test.run_mf6(Simulation(exdir, exfunc=eval_heads, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test models - for idx, exdir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, exdir) - - sim = Simulation(exdir, exfunc=eval_heads, idxsim=idx) - test.run_mf6(sim) - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_heads, idxsim=idx), ws) diff --git a/autotest/test_gwt_adv01.py b/autotest/test_gwt_adv01.py index 3afcf22e605..87b6b8eee1e 100644 --- a/autotest/test_gwt_adv01.py +++ b/autotest/test_gwt_adv01.py @@ -6,28 +6,15 @@ """ import os -import sys +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["adv01a", "adv01b", "adv01c"] scheme = ["upstream", "central", "tvd"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" def build_model(idx, dir): @@ -601,42 +588,13 @@ def eval_transport(sim): creslist[sim.idxsim], conc ), "simulated concentrations do not match with known solution." - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=idx), ws) diff --git a/autotest/test_gwt_adv01_fmi.py b/autotest/test_gwt_adv01_fmi.py index 98a08712210..f47285f53c3 100644 --- a/autotest/test_gwt_adv01_fmi.py +++ b/autotest/test_gwt_adv01_fmi.py @@ -6,29 +6,17 @@ """ import os -import sys +import flopy import numpy as np import pytest +from flopy.utils.binaryfile import write_head, write_budget +from flopy.utils.gridutil import uniform_flow_field -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from binary_file_writer import uniform_flow_field, write_budget, write_head -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["adv01a_fmi", "adv01b_fmi", "adv01c_fmi"] scheme = ["upstream", "central", "tvd"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" def build_model(idx, dir): @@ -576,42 +564,13 @@ def eval_transport(sim): creslist[sim.idxsim], conc ), "simulated concentrations do not match with known solution." - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=idx), ws) diff --git a/autotest/test_gwt_adv01_gwtgwt.py b/autotest/test_gwt_adv01_gwtgwt.py index 42c47128abf..2a25e79d335 100644 --- a/autotest/test_gwt_adv01_gwtgwt.py +++ b/autotest/test_gwt_adv01_gwtgwt.py @@ -7,28 +7,14 @@ import os +import flopy import numpy as np import pytest -from matplotlib import pyplot as plt -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["adv01a_gwtgwt", "adv01b_gwtgwt", "adv01c_gwtgwt"] scheme = ["upstream", "central", "tvd"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" - gdelr = 1.0 @@ -739,43 +725,13 @@ def eval_transport(sim): # TODO: this is not implemented yet: # assert np.allclose(res, 0.0, atol=1.0e-6), errmsg - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -@pytest.mark.developmode -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=idx), ws) diff --git a/autotest/test_gwt_adv02.py b/autotest/test_gwt_adv02.py index 39942b02189..d2139741ec9 100644 --- a/autotest/test_gwt_adv02.py +++ b/autotest/test_gwt_adv02.py @@ -8,29 +8,16 @@ """ import os -import sys +import flopy +import flopy.utils.cvfdutil import numpy as np import pytest -try: - import flopy - import flopy.utils.cvfdutil -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["adv02a", "adv02b", "adv02c"] scheme = ["upstream", "central", "tvd"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" def grid_triangulator(itri, delr, delc): @@ -954,42 +941,13 @@ def eval_transport(sim): creslist[sim.idxsim], conc ), "simulated concentrations do not match with known solution." - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=idx), ws) diff --git a/autotest/test_gwt_adv03.py b/autotest/test_gwt_adv03.py index db6014f586d..b61fba7bb12 100644 --- a/autotest/test_gwt_adv03.py +++ b/autotest/test_gwt_adv03.py @@ -8,29 +8,16 @@ """ import os -import sys +import flopy +import flopy.utils.cvfdutil import numpy as np import pytest -try: - import flopy - import flopy.utils.cvfdutil -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["adv03a", "adv03b", "adv03c"] scheme = ["upstream", "central", "tvd"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" def grid_triangulator(itri, delr, delc): @@ -506,42 +493,13 @@ def eval_transport(sim): conc[0, 0, -ncellsperrow:], ) - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=idx), ws) diff --git a/autotest/test_gwt_adv04.py b/autotest/test_gwt_adv04.py index 9bb743fe91d..92231b08d66 100644 --- a/autotest/test_gwt_adv04.py +++ b/autotest/test_gwt_adv04.py @@ -7,36 +7,15 @@ """ import os -import sys +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["adv04a", "adv04b", "adv04c"] scheme = ["upstream", "central", "tvd"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" def build_model(idx, dir): @@ -277,44 +256,13 @@ def eval_transport(sim): "symmetric in left-right direction." ) - return - - -# - No need to change any code below - @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=idx), ws) diff --git a/autotest/test_gwt_buy_solute_heat.py b/autotest/test_gwt_buy_solute_heat.py index b1a7f0b818a..bdad2631da3 100644 --- a/autotest/test_gwt_buy_solute_heat.py +++ b/autotest/test_gwt_buy_solute_heat.py @@ -1,24 +1,12 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["gwtbuy"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) def build_model(idx, dir): @@ -342,8 +330,8 @@ def build_model(idx, dir): def make_plot(sim): print("making plots...") - name = ex[sim.idxsim] - ws = exdirs[sim.idxsim] + name = sim.name + ws = sim.simpath sim = flopy.mf6.MFSimulation.load(sim_ws=ws) gwfname = "flow" gwtsname = "salinity" @@ -429,7 +417,6 @@ def eval_transport(sim): if makeplot: make_plot(sim) - name = ex[sim.idxsim] ws = sim.simpath gwfname = "flow" gwtsname = "salinity" @@ -473,44 +460,14 @@ def eval_transport(sim): np.savetxt(fname, densecalculated.reshape(200, 100)) assert False, "density is not correct" - # assert False - - return - -# - No need to change any code below +@pytest.mark.slow @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=0), ws) diff --git a/autotest/test_gwt_disu01.py b/autotest/test_gwt_disu01.py index 45e33a5602e..41a7447e783 100644 --- a/autotest/test_gwt_disu01.py +++ b/autotest/test_gwt_disu01.py @@ -7,41 +7,18 @@ """ import os -import sys +import flopy import numpy as np import pytest +from flopy.utils.gridutil import get_disu_kwargs -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from disu_util import get_disu_kwargs -from framework import testing_framework -from simulation import Simulation - -ex = [ - "disu01a", -] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" - - -def build_model(idx, dir): +from harness import TestHarness, TestConfig + +ex = ["disu01a"] + + +def build_model(idx, dir, exe): nlay, nrow, ncol = 1, 21, 21 nper = 1 perlen = [5.0] @@ -87,7 +64,7 @@ def get_nn(k, i, j): # build MODFLOW 6 files ws = dir sim = flopy.mf6.MFSimulation( - sim_name=name, version="mf6", exe_name="mf6", sim_ws=ws + sim_name=name, version="mf6", exe_name=exe, sim_ws=ws ) # create tdis package tdis = flopy.mf6.ModflowTdis( @@ -246,7 +223,7 @@ def get_nn(k, i, j): def eval_transport(sim): print("evaluating transport...") - name = ex[sim.idxsim] + name = sim.name gwtname = "gwt_" + name fpth = os.path.join(sim.simpath, f"{gwtname}.ucn") @@ -272,44 +249,14 @@ def eval_transport(sim): "symmetric in left-right direction." ) - return - - -# - No need to change any code below - @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + mf6 = targets.mf6 + test = TestHarness() + test.build(lambda i, w: build_model(i, w, mf6), 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=0), ws) diff --git a/autotest/test_gwt_dsp01.py b/autotest/test_gwt_dsp01.py index ad11fc51c19..2bb42076f92 100644 --- a/autotest/test_gwt_dsp01.py +++ b/autotest/test_gwt_dsp01.py @@ -1,34 +1,14 @@ import os -import sys import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +import flopy + +from harness import TestHarness, TestConfig ex = ["dsp01a", "dsp01b"] xt3d = [False, True] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" def build_model(idx, dir): @@ -406,42 +386,13 @@ def eval_transport(sim): # comment when done testing # assert False - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=idx), ws) diff --git a/autotest/test_gwt_dsp01_fmi.py b/autotest/test_gwt_dsp01_fmi.py index 10a7e5c5189..0f00cb84564 100644 --- a/autotest/test_gwt_dsp01_fmi.py +++ b/autotest/test_gwt_dsp01_fmi.py @@ -1,35 +1,14 @@ import os -import sys +import flopy import numpy as np import pytest +from flopy.utils.binaryfile import write_head, write_budget -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from binary_file_writer import write_budget, write_head -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["dsp01a_fmi", "dsp01b_fmi"] xt3d = [False, True] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" def build_model(idx, dir): @@ -340,42 +319,13 @@ def eval_transport(sim): cres, conc ), "simulated concentrations do not match with known solution." - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=idx), ws) diff --git a/autotest/test_gwt_dsp01_gwtgwt.py b/autotest/test_gwt_dsp01_gwtgwt.py index d7d01e6fe05..eb1ff3b116d 100644 --- a/autotest/test_gwt_dsp01_gwtgwt.py +++ b/autotest/test_gwt_dsp01_gwtgwt.py @@ -6,27 +6,13 @@ import os +import flopy import numpy as np import pytest -from matplotlib import pyplot as plt -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["dsp01_gwtgwt"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" - gdelr = 1.0 @@ -311,43 +297,13 @@ def eval_transport(sim): # no loss of solute assert abs(np.sum(conc1) + np.sum(conc2) - 100.0) < 1e-6 - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -@pytest.mark.developmode -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=idx), ws) diff --git a/autotest/test_gwt_dsp01_noadv.py b/autotest/test_gwt_dsp01_noadv.py index 230d3711752..b17bcdd87bc 100644 --- a/autotest/test_gwt_dsp01_noadv.py +++ b/autotest/test_gwt_dsp01_noadv.py @@ -1,34 +1,13 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["dsp01a_noadv", "dsp01b_noadv"] xt3d = [False, True] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" def build_model(idx, dir): @@ -284,42 +263,13 @@ def eval_transport(sim): cres, conc ), "simulated concentrations do not match with known solution." - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=idx), ws) diff --git a/autotest/test_gwt_dsp02.py b/autotest/test_gwt_dsp02.py index d2e0d7f0613..aedea842db4 100644 --- a/autotest/test_gwt_dsp02.py +++ b/autotest/test_gwt_dsp02.py @@ -8,29 +8,16 @@ """ import os -import sys +import flopy +import flopy.utils.cvfdutil import numpy as np import pytest -try: - import flopy - import flopy.utils.cvfdutil -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["dsp02a", "dsp02b"] xt3d = [True, False] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" def grid_triangulator(itri, delr, delc): @@ -725,42 +712,13 @@ def eval_transport(sim): creslist[sim.idxsim], conc ), "simulated concentrations do not match with known solution." - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=idx), ws) diff --git a/autotest/test_gwt_dsp03.py b/autotest/test_gwt_dsp03.py index 960de6fe324..d3bdd52ece4 100644 --- a/autotest/test_gwt_dsp03.py +++ b/autotest/test_gwt_dsp03.py @@ -8,29 +8,16 @@ """ import os -import sys +import flopy +import flopy.utils.cvfdutil import numpy as np import pytest -try: - import flopy - import flopy.utils.cvfdutil -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["dsp03a", "dsp03b"] xt3d = [False, True] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" def grid_triangulator(itri, delr, delc): @@ -451,42 +438,14 @@ def eval_transport(sim): conc[0, 0, -ncellsperrow:], ) - return - -# - No need to change any code below +@pytest.mark.slow @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=idx), ws) diff --git a/autotest/test_gwt_dsp04.py b/autotest/test_gwt_dsp04.py index 85724e4856d..7b7a4c0e622 100644 --- a/autotest/test_gwt_dsp04.py +++ b/autotest/test_gwt_dsp04.py @@ -1,35 +1,14 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig # test dispersion without and with xt3d ex = ["dsp04a", "dsp04b"] xt3d = [None, True] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" def build_model(idx, dir): @@ -271,44 +250,13 @@ def eval_transport(sim): "symmetric in left-right direction." ) - return - - -# - No need to change any code below - @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=idx), ws) diff --git a/autotest/test_gwt_dsp05_noadv.py b/autotest/test_gwt_dsp05_noadv.py index a5852b2132e..13c6182ffcd 100644 --- a/autotest/test_gwt_dsp05_noadv.py +++ b/autotest/test_gwt_dsp05_noadv.py @@ -7,34 +7,14 @@ """ import os +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["dsp05a_noadv", "dsp01b_noadv"] xt3d = [False, True] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" def build_model(idx, dir): @@ -180,42 +160,13 @@ def eval_transport(sim): msg = f"simulated concentrations do not match with known solution. {conc} {cres}" assert np.allclose(cres, conc.flatten()), msg - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=idx), ws) diff --git a/autotest/test_gwt_fmi01.py b/autotest/test_gwt_fmi01.py index 52d4c3680f6..9b387ae8f68 100644 --- a/autotest/test_gwt_fmi01.py +++ b/autotest/test_gwt_fmi01.py @@ -1,37 +1,15 @@ import os -import sys +import flopy +from flopy.utils.binaryfile import write_head, write_budget +from flopy.utils.gridutil import uniform_flow_field import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) +from harness import TestHarness, TestConfig -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from binary_file_writer import uniform_flow_field, write_budget, write_head -from framework import testing_framework -from simulation import Simulation - -ex = [ - "fmi01a_fc", -] +ex = ["fmi01a_fc"] xt3d = [False, True] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" def build_model(idx, dir): @@ -198,17 +176,14 @@ def build_model(idx, dir): def eval_transport(sim): print("evaluating transport...") - name = ex[sim.idxsim] + name = sim.name gwtname = "gwt_" + name fpth = os.path.join(sim.simpath, f"{gwtname}.ucn") - try: - cobj = flopy.utils.HeadFile( - fpth, precision="double", text="CONCENTRATION" - ) - conc = cobj.get_data() - except: - assert False, f'could not load data from "{fpth}"' + cobj = flopy.utils.HeadFile( + fpth, precision="double", text="CONCENTRATION" + ) + conc = cobj.get_data() # This is the answer to this problem. Concentration should not change cres = [[[10, 10, 10]]] @@ -217,42 +192,13 @@ def eval_transport(sim): errmsg += f"cres: {cres}\ncans:{conc}" assert np.allclose(cres, conc), errmsg - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=0), ws) diff --git a/autotest/test_gwt_fmi02.py b/autotest/test_gwt_fmi02.py index 032d47b309f..61d17c952fd 100644 --- a/autotest/test_gwt_fmi02.py +++ b/autotest/test_gwt_fmi02.py @@ -1,44 +1,17 @@ # tests to ability to run flow model first followed by transport model import os -import shutil -import numpy as np -import pytest +import flopy -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - - -import targets - -exe_name_mf6 = targets.target_dict["mf6"] -exe_name_mf6 = os.path.abspath(exe_name_mf6) -testdir = "./temp" testgroup = "fmi02" -d = os.path.join(testdir, testgroup) -if os.path.isdir(d): - shutil.rmtree(d) -def run_flow_model(): +def run_flow_model(dir, exe): name = "flow" - ws = os.path.join(testdir, testgroup, name) + ws = os.path.join(dir, testgroup, name) sim = flopy.mf6.MFSimulation( - sim_name=name, sim_ws=ws, exe_name=exe_name_mf6 + sim_name=name, sim_ws=ws, exe_name=exe ) pd = [(1.0, 1, 1.0), (1.0, 1, 1.0)] tdis = flopy.mf6.ModflowTdis(sim, nper=len(pd), perioddata=pd) @@ -70,14 +43,13 @@ def run_flow_model(): assert os.path.isfile(fname) fname = os.path.join(ws, head_file) assert os.path.isfile(fname) - return -def run_transport_model(): +def run_transport_model(dir, exe): name = "transport" - ws = os.path.join(testdir, testgroup, name) + ws = os.path.join(dir, testgroup, name) sim = flopy.mf6.MFSimulation( - sim_name=name, sim_ws=ws, exe_name=exe_name_mf6 + sim_name=name, sim_ws=ws, exe_name=exe ) pd = [(1.0, 10, 1.0), (1.0, 10, 1.0)] tdis = flopy.mf6.ModflowTdis(sim, nper=len(pd), perioddata=pd) @@ -106,21 +78,9 @@ def run_transport_model(): assert os.path.isfile(fname) fname = os.path.join(ws, concentration_file) assert os.path.isfile(fname) - return - - -def test_fmi(): - run_flow_model() - run_transport_model() - d = os.path.join(testdir, testgroup) - if os.path.isdir(d): - shutil.rmtree(d) - return - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - # run tests - test_fmi() +def test_fmi(function_tmpdir, targets): + mf6 = targets["mf6"] + run_flow_model(str(function_tmpdir), mf6) + run_transport_model(str(function_tmpdir), mf6) diff --git a/autotest/test_gwt_henry.py b/autotest/test_gwt_henry.py index 6b7eae4478c..24180ea840d 100644 --- a/autotest/test_gwt_henry.py +++ b/autotest/test_gwt_henry.py @@ -1,24 +1,12 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["henry01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) def build_model(idx, dir): @@ -246,7 +234,7 @@ def chd_value(k): def eval_transport(sim): print("evaluating transport...") - name = ex[sim.idxsim] + name = sim.name gwtname = "gwt_" + name fpth = os.path.join(sim.simpath, f"{gwtname}.ucn") @@ -300,42 +288,13 @@ def eval_transport(sim): conc[-1, :, :], ) - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=0), ws) diff --git a/autotest/test_gwt_henry_nr.py b/autotest/test_gwt_henry_nr.py index b410def2e20..65d629a3ba8 100644 --- a/autotest/test_gwt_henry_nr.py +++ b/autotest/test_gwt_henry_nr.py @@ -6,26 +6,14 @@ # the effects of tides on the aquifer. import os -import sys +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["henrynr01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) # global model variables nlay = 20 @@ -388,8 +376,8 @@ def get_patch_collection(modelgrid, head, conc, cmap="jet", zorder=None): def make_plot(sim, headall, concall): print("making plots...") - name = ex[sim.idxsim] - ws = exdirs[sim.idxsim] + name = sim.name + ws = sim.simpath sim = flopy.mf6.MFSimulation.load(sim_ws=ws) gwfname = "gwf_" + name gwtname = "gwt_" + name @@ -472,14 +460,12 @@ def make_plot(sim, headall, concall): fname = os.path.join(ws, fname) plt.savefig(fname, bbox_inches="tight") - return - def eval_transport(sim): print("evaluating transport...") - name = ex[sim.idxsim] - ws = exdirs[sim.idxsim] + name = sim.name + ws = sim.simpath gwfname = "gwf_" + name gwtname = "gwt_" + name @@ -540,42 +526,14 @@ def eval_transport(sim): make_plot(sim, head, conc) assert False - return - -# - No need to change any code below +@pytest.mark.slow @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=idx), ws) diff --git a/autotest/test_gwt_henry_openclose.py b/autotest/test_gwt_henry_openclose.py index 596d9e84708..0744d3d4a5e 100644 --- a/autotest/test_gwt_henry_openclose.py +++ b/autotest/test_gwt_henry_openclose.py @@ -1,24 +1,12 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["henry_ext"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) def build_model(idx, dir): @@ -249,7 +237,7 @@ def chd_value(k): def eval_transport(sim): print("evaluating transport...") - name = ex[sim.idxsim] + name = sim.name gwtname = "gwt_" + name fpth = os.path.join(sim.simpath, f"{gwtname}.ucn") @@ -303,42 +291,13 @@ def eval_transport(sim): conc[-1, :, :], ) - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=0), ws) diff --git a/autotest/test_gwt_ims_issue655.py b/autotest/test_gwt_ims_issue655.py index 07ef7b8bf6c..672b1868da2 100644 --- a/autotest/test_gwt_ims_issue655.py +++ b/autotest/test_gwt_ims_issue655.py @@ -8,27 +8,11 @@ import os +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["issue655a", "issue655b"] newton = [ @@ -38,9 +22,6 @@ laytyp = [1] ss = [1.0e-10] sy = [0.1] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) nlay, nrow, ncol = 1, 11, 11 @@ -310,39 +291,13 @@ def eval_transport(sim): # assert np.allclose(c, conc_calc, atol=0.001), msg # vold = v - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, exdir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, exdir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, exdir) - - # run the test model - test.run_mf6(Simulation(exdir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build and run the test model - for idx, exdir in enumerate(exdirs): - test_mf6model(idx, exdir) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=idx), ws) diff --git a/autotest/test_gwt_ist01.py b/autotest/test_gwt_ist01.py index b9ea2a9ea4e..be27db0b840 100644 --- a/autotest/test_gwt_ist01.py +++ b/autotest/test_gwt_ist01.py @@ -6,27 +6,11 @@ import os +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["ist01"] laytyp = [1] @@ -34,10 +18,6 @@ sy = [0.1] thetaim = [0.05] zetaim = [0.1] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" nlay, nrow, ncol = 1, 1, 1 @@ -243,27 +223,21 @@ def build_model(idx, dir): def eval_transport(sim): print("evaluating transport...") - name = ex[sim.idxsim] + name = sim.name gwtname = "gwt_" + name gwfname = "gwf_" + name # head fpth = os.path.join(sim.simpath, f"{gwfname}.hds") - try: - hobj = flopy.utils.HeadFile(fpth, precision="double") - head = hobj.get_alldata().flatten() - except: - assert False, f'could not load data from "{fpth}"' + hobj = flopy.utils.HeadFile(fpth, precision="double") + head = hobj.get_alldata().flatten() # mobile concentration fpth = os.path.join(sim.simpath, f"{gwtname}.ucn") - try: - cobj = flopy.utils.HeadFile( - fpth, precision="double", text="CONCENTRATION" - ) - conc = cobj.get_alldata().flatten() - except: - assert False, f'could not load data from "{fpth}"' + cobj = flopy.utils.HeadFile( + fpth, precision="double", text="CONCENTRATION" + ) + conc = cobj.get_alldata().flatten() # immobile concentration fpth = os.path.join(sim.simpath, f"{gwtname}.ist.ucn") @@ -288,48 +262,19 @@ def eval_transport(sim): saturation = 0.5 volume = 10.0 * 10.0 * 10.0 rate_calc = ( - (cim[i] - conc[i]) * zetaim[sim.idxsim] * saturation * volume + (cim[i] - conc[i]) * zetaim[0] * saturation * volume ) print(t, conc[i], cim[i], rate_sim, rate_calc) msg = f"Rate: {rate_sim} /= {rate_calc} for time {t}" assert np.allclose(rate_sim, rate_calc), msg - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=0), ws) diff --git a/autotest/test_gwt_lkt01.py b/autotest/test_gwt_lkt01.py index e3407bbafdb..64c89e4547b 100644 --- a/autotest/test_gwt_lkt01.py +++ b/autotest/test_gwt_lkt01.py @@ -4,26 +4,14 @@ # leaks into the aquifer. import os -import sys +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["lkt_01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) def build_model(idx, dir): @@ -346,14 +334,14 @@ def build_model(idx, dir): def get_mfsim(testsim): - ws = exdirs[testsim.idxsim] + ws = testsim.simpath sim = flopy.mf6.MFSimulation.load(sim_ws=ws) return sim def eval_csv_information(testsim): sim = get_mfsim(testsim) - name = ex[testsim.idxsim] + name = testsim.name gwfname = "gwf_" + name gwtname = "gwt_" + name gwf = sim.get_model(gwfname) @@ -364,8 +352,6 @@ def eval_csv_information(testsim): answer = np.zeros(result.shape) assert np.allclose(result, answer), f"Lake package does not have zero mass balance error: {result}" - return - def eval_results(sim): print("evaluating results...") @@ -374,7 +360,7 @@ def eval_results(sim): eval_csv_information(sim) # ensure lake concentrations were saved - name = ex[sim.idxsim] + name = sim.name gwtname = "gwt_" + name fname = gwtname + ".lkt.bin" fname = os.path.join(sim.simpath, fname) @@ -444,39 +430,13 @@ def eval_results(sim): # uncomment when testing # assert False - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_results, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_results, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_results, idxsim=idx), ws) diff --git a/autotest/test_gwt_lkt02.py b/autotest/test_gwt_lkt02.py index 412ebc19ae9..ea2ab9731e6 100644 --- a/autotest/test_gwt_lkt02.py +++ b/autotest/test_gwt_lkt02.py @@ -2,26 +2,14 @@ # move solute from one lake to another. import os -import sys +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["lkt_02"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) def build_model(idx, dir): @@ -368,7 +356,7 @@ def eval_results(sim): print("evaluating results...") # ensure lake concentrations were saved - name = ex[sim.idxsim] + name = sim.name gwtname = "gwt_" + name fname = gwtname + ".lkt.bin" fname = os.path.join(sim.simpath, fname) @@ -497,39 +485,13 @@ def eval_results(sim): # uncomment when testing # assert False - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_results, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_results, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_results, idxsim=0), ws) diff --git a/autotest/test_gwt_lkt03.py b/autotest/test_gwt_lkt03.py index d89912be6ec..b0e9909561c 100644 --- a/autotest/test_gwt_lkt03.py +++ b/autotest/test_gwt_lkt03.py @@ -2,26 +2,14 @@ # such as rainfall to make sure mixing is calculated correctly. import os -import sys +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["lkt_03"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) def build_model(idx, dir): @@ -348,7 +336,7 @@ def eval_results(sim): print("evaluating results...") # ensure lake concentrations were saved - name = ex[sim.idxsim] + name = sim.name gwtname = "gwt_" + name fname = gwtname + ".lkt.bin" fname = os.path.join(sim.simpath, fname) @@ -393,39 +381,13 @@ def eval_results(sim): # uncomment when testing # assert False - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_results, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_results, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_results, idxsim=0), ws) diff --git a/autotest/test_gwt_lkt04.py b/autotest/test_gwt_lkt04.py index 7a906bb9000..95381c0f6e3 100644 --- a/autotest/test_gwt_lkt04.py +++ b/autotest/test_gwt_lkt04.py @@ -5,27 +5,17 @@ # should remain at zero. import os + +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["lkt_04"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -def build_model(idx, dir): +def build_model(idx, dir, exe): lx = 5.0 lz = 1.0 nlay = 1 @@ -59,9 +49,8 @@ def build_model(idx, dir): name = ex[idx] # build MODFLOW 6 files - ws = dir sim = flopy.mf6.MFSimulation( - sim_name=name, version="mf6", exe_name="mf6", sim_ws=ws + sim_name=name, version="mf6", exe_name=exe, sim_ws=dir ) # create tdis package tdis = flopy.mf6.ModflowTdis( @@ -345,14 +334,14 @@ def build_model(idx, dir): def get_mfsim(testsim): - ws = exdirs[testsim.idxsim] + ws = testsim.simpath sim = flopy.mf6.MFSimulation.load(sim_ws=ws) return sim def eval_csv_information(testsim): sim = get_mfsim(testsim) - name = ex[testsim.idxsim] + name = testsim.name gwfname = "gwf_" + name gwtname = "gwt_" + name gwf = sim.get_model(gwfname) @@ -381,8 +370,6 @@ def eval_csv_information(testsim): assert success, f"One or more errors encountered in budget checks" - return - def eval_results(sim): print("evaluating results...") @@ -391,7 +378,7 @@ def eval_results(sim): eval_csv_information(sim) # ensure lake concentrations were saved - name = ex[sim.idxsim] + name = sim.name gwtname = "gwt_" + name fname = gwtname + ".lkt.bin" fname = os.path.join(sim.simpath, fname) @@ -485,39 +472,14 @@ def eval_results(sim): # uncomment when testing # assert False - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_results, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_results, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + mf6 = targets["mf6"] + test = TestHarness() + test.build(lambda i, w: build_model(i, w, mf6), idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_results, idxsim=idx), ws) diff --git a/autotest/test_gwt_moc3d01.py b/autotest/test_gwt_moc3d01.py index 6aa18374340..e00207a7650 100644 --- a/autotest/test_gwt_moc3d01.py +++ b/autotest/test_gwt_moc3d01.py @@ -1,27 +1,10 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = [ "moc3d01a", @@ -38,10 +21,6 @@ retardation = [None, None, None, None, 40.0, 4.0, 2.0, None] perlens = 4 * [120.0] + 3 * [240.0] + [120.0] decay = 7 * [None] + [0.01] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" def build_model(idx, dir): @@ -371,44 +350,13 @@ def eval_transport(sim): tsres, tssim ), "simulated concentrations do not match with known solution." - return - - -# - No need to change any code below - @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=idx), ws) diff --git a/autotest/test_gwt_moc3d01_zod.py b/autotest/test_gwt_moc3d01_zod.py index 30ad34d1b99..d5499784b40 100644 --- a/autotest/test_gwt_moc3d01_zod.py +++ b/autotest/test_gwt_moc3d01_zod.py @@ -5,29 +5,12 @@ # where concentrations are zero. import os -import sys +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = [ "moc3d01zoda", @@ -38,10 +21,6 @@ retardation = [None, 40, None, 40] decay = [0.01, 0.01, 0.1, 0.1] ist_package = [False, False, True, True] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" def build_model(idx, dir): @@ -441,11 +420,11 @@ def eval_transport(sim): makeplot = False if makeplot: fname = "fig-ct.pdf" - fname = os.path.join(exdirs[sim.idxsim], fname) + fname = os.path.join(ex[sim.idxsim], fname) make_plot_ct(tssim, fname) fname = "fig-cd.pdf" - fname = os.path.join(exdirs[sim.idxsim], fname) + fname = os.path.join(ex[sim.idxsim], fname) make_plot_cd(cobj, fname) tssim = tssim[::10] @@ -577,44 +556,13 @@ def eval_transport(sim): if tsres is not None: assert np.allclose(tsres, tssim), errmsg - return - - -# - No need to change any code below - @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=idx), ws) diff --git a/autotest/test_gwt_moc3d02.py b/autotest/test_gwt_moc3d02.py index 7b349b471aa..da5862625c5 100644 --- a/autotest/test_gwt_moc3d02.py +++ b/autotest/test_gwt_moc3d02.py @@ -1,34 +1,13 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["moc3d02a", "moc3d02b"] xt3d = [None, True] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" def build_model(idx, dir): @@ -329,42 +308,14 @@ def eval_transport(sim): cres, csim, rtol=1.0e-4 ), "simulated concentrations do not match with known solution." - return - -# - No need to change any code below +@pytest.mark.slow @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=idx), ws) diff --git a/autotest/test_gwt_moc3d03.py b/autotest/test_gwt_moc3d03.py index 866c2d9df1e..4c0397fb467 100644 --- a/autotest/test_gwt_moc3d03.py +++ b/autotest/test_gwt_moc3d03.py @@ -1,33 +1,12 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["moc3d03"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" def build_model(idx, dir): @@ -258,7 +237,7 @@ def build_model(idx, dir): def eval_transport(sim): print("evaluating transport...") - name = ex[sim.idxsim] + name = sim.name gwtname = "gwt_" + name fpth = os.path.join(sim.simpath, f"{gwtname}.ucn") @@ -311,42 +290,14 @@ def eval_transport(sim): cres, csim.diagonal().ravel() ), "simulated concentrations do not match with known solution." - return - -# - No need to change any code below +@pytest.mark.slow @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=0), ws) diff --git a/autotest/test_gwt_mst01.py b/autotest/test_gwt_mst01.py index e732c1c1ce7..a41f4075ed0 100644 --- a/autotest/test_gwt_mst01.py +++ b/autotest/test_gwt_mst01.py @@ -1,36 +1,15 @@ import os -import sys +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["mst01"] laytyp = [1] ss = [0.0] sy = [0.1] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" nlay, nrow, ncol = 4, 1, 1 @@ -240,17 +219,14 @@ def build_model(idx, dir): def eval_transport(sim): print("evaluating transport...") - name = ex[sim.idxsim] + name = sim.name gwtname = "gwt_" + name fpth = os.path.join(sim.simpath, f"{gwtname}.ucn") - try: - cobj = flopy.utils.HeadFile( - fpth, precision="double", text="CONCENTRATION" - ) - conc1 = cobj.get_data(totim=3.0) - except: - assert False, f'could not load data from "{fpth}"' + cobj = flopy.utils.HeadFile( + fpth, precision="double", text="CONCENTRATION" + ) + conc1 = cobj.get_data(totim=3.0) # end of stress period 1 cres1 = np.ones((nlay, nrow, ncol), float) @@ -258,42 +234,13 @@ def eval_transport(sim): "simulated concentrations do not match " "with known solution." ) - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=0), ws) diff --git a/autotest/test_gwt_mst02.py b/autotest/test_gwt_mst02.py index 410ec71309d..2373afe249e 100644 --- a/autotest/test_gwt_mst02.py +++ b/autotest/test_gwt_mst02.py @@ -3,36 +3,15 @@ """ import os -import sys +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["mst02a", "mst02b"] distcoef = [0.0, 1.0] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" nlay, nrow, ncol = 1, 1, 2 # time series answers for the two simulations @@ -277,42 +256,13 @@ def eval_transport(sim): except: assert False, f'could not load data from "{fpth}"' - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=idx), ws) diff --git a/autotest/test_gwt_mst03.py b/autotest/test_gwt_mst03.py index 7a4874e966c..1496c84ecf0 100644 --- a/autotest/test_gwt_mst03.py +++ b/autotest/test_gwt_mst03.py @@ -7,36 +7,16 @@ import os +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["mst03"] laytyp = [1] ss = [1.0e-10] sy = [0.1] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" nlay, nrow, ncol = 1, 1, 1 @@ -238,25 +218,19 @@ def build_model(idx, dir): def eval_transport(sim): print("evaluating transport...") - name = ex[sim.idxsim] + name = sim.name gwtname = "gwt_" + name gwfname = "gwf_" + name fpth = os.path.join(sim.simpath, f"{gwfname}.hds") - try: - hobj = flopy.utils.HeadFile(fpth, precision="double") - head = hobj.get_alldata().flatten() - except: - assert False, f'could not load data from "{fpth}"' + hobj = flopy.utils.HeadFile(fpth, precision="double") + head = hobj.get_alldata().flatten() fpth = os.path.join(sim.simpath, f"{gwtname}.ucn") - try: - cobj = flopy.utils.HeadFile( - fpth, precision="double", text="CONCENTRATION" - ) - conc = cobj.get_alldata().flatten() - except: - assert False, f'could not load data from "{fpth}"' + cobj = flopy.utils.HeadFile( + fpth, precision="double", text="CONCENTRATION" + ) + conc = cobj.get_alldata().flatten() # calculations times = hobj.get_times() @@ -312,42 +286,13 @@ def eval_transport(sim): errmsg = f"{conc}\n{canswer}" assert np.allclose(conc, canswer, atol=1.0e-8), errmsg - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=0), ws) diff --git a/autotest/test_gwt_mst04_noadv.py b/autotest/test_gwt_mst04_noadv.py index d4fc01c690e..ca7a08f8b6f 100644 --- a/autotest/test_gwt_mst04_noadv.py +++ b/autotest/test_gwt_mst04_noadv.py @@ -6,35 +6,13 @@ """ import os +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation - -ex = [ - "mst04_noadv", -] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" +from harness import TestHarness, TestConfig + +ex = ["mst04_noadv"] def build_model(idx, dir): @@ -134,59 +112,27 @@ def build_model(idx, dir): def eval_transport(sim): print("evaluating transport...") - name = ex[sim.idxsim] + name = sim.name gwtname = "gwt_" + name fpth = os.path.join(sim.simpath, f"{gwtname}.ucn") - try: - cobj = flopy.utils.HeadFile( - fpth, precision="double", text="CONCENTRATION" - ) - conc = cobj.get_data() - except: - assert False, f'could not load data from "{fpth}"' + cobj = flopy.utils.HeadFile( + fpth, precision="double", text="CONCENTRATION" + ) + conc = cobj.get_data() # The answer 1 cres = np.array([10.0]) msg = f"simulated concentrations do not match with known solution. {conc} {cres}" assert np.allclose(cres, conc.flatten()), msg - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=0), ws) diff --git a/autotest/test_gwt_mst05.py b/autotest/test_gwt_mst05.py index 4999f5a3c89..319fc000c9e 100644 --- a/autotest/test_gwt_mst05.py +++ b/autotest/test_gwt_mst05.py @@ -5,22 +5,14 @@ """ import os -import sys +import flopy import numpy as np import pytest +from flopy.utils.binaryfile import write_head, write_budget +from flopy.utils.gridutil import uniform_flow_field -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from binary_file_writer import uniform_flow_field, write_budget, write_head -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["mst05a", "mst05b"] isotherm = ["freundlich", "langmuir"] @@ -28,10 +20,6 @@ sp2 = [0.7, 0.003] xmax_plot = [1500, 500] ymax_plot = [0.5, 1.0] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" def build_model(idx, dir): @@ -319,42 +307,13 @@ def eval_transport(sim): fname = os.path.join(sim.simpath, "results.png") plt.savefig(fname) - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=idx), ws) diff --git a/autotest/test_gwt_mst06_noadv.py b/autotest/test_gwt_mst06_noadv.py index 26710b34e9d..1035da8c754 100644 --- a/autotest/test_gwt_mst06_noadv.py +++ b/autotest/test_gwt_mst06_noadv.py @@ -7,35 +7,13 @@ """ import os +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation - -ex = [ - "mst06_noadv", -] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" +from harness import TestHarness, TestConfig + +ex = ["mst06_noadv"] def build_model(idx, dir): @@ -144,17 +122,14 @@ def build_model(idx, dir): def eval_transport(sim): print("evaluating transport...") - name = ex[sim.idxsim] + name = sim.name gwtname = "gwt_" + name fpth = os.path.join(sim.simpath, f"{gwtname}.ucn") - try: - cobj = flopy.utils.HeadFile( - fpth, precision="double", text="CONCENTRATION" - ) - conc = cobj.get_ts((0, 0, 0)) - except: - assert False, f'could not load data from "{fpth}"' + cobj = flopy.utils.HeadFile( + fpth, precision="double", text="CONCENTRATION" + ) + conc = cobj.get_ts((0, 0, 0)) # The answer # print(conc[:, 1]) @@ -191,42 +166,13 @@ def eval_transport(sim): ) assert np.allclose(decay_rate, decay_rate_answer), msg - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=0), ws) diff --git a/autotest/test_gwt_mt3dms_p01.py b/autotest/test_gwt_mt3dms_p01.py index 43e8da72055..616f93135c3 100644 --- a/autotest/test_gwt_mt3dms_p01.py +++ b/autotest/test_gwt_mt3dms_p01.py @@ -20,36 +20,12 @@ """ import os -import shutil -import sys +import flopy import numpy as np -import pytest - -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -import targets - -exe_name_mf = targets.target_dict["mf2005s"] -exe_name_mt = targets.target_dict["mt3dms"] -exe_name_mf6 = targets.target_dict["mf6"] -testdir = "./temp" + + testgroup = "mt3dms_p01" -remove_files = True def p01mt3d( @@ -62,6 +38,8 @@ def p01mt3d( prsity2=None, rc2=None, zero_order_decay=False, + mf2005s="mf2005s", + mt3dms="mt3dms" ): nlay = 1 nrow = 1 @@ -85,7 +63,7 @@ def p01mt3d( modelname_mf = "p01_mf" mf = flopy.modflow.Modflow( - modelname=modelname_mf, model_ws=model_ws, exe_name=exe_name_mf + modelname=modelname_mf, model_ws=model_ws, exe_name=mf2005s ) dis = flopy.modflow.ModflowDis( mf, @@ -115,7 +93,7 @@ def p01mt3d( mt = flopy.mt3d.Mt3dms( modelname=modelname_mt, model_ws=model_ws, - exe_name=exe_name_mt, + exe_name=mt3dms, modflowmodel=mf, ) c0 = 1.0 @@ -209,6 +187,7 @@ def p01mf6( prsity2=None, onelambda=False, zero_order_decay=False, + exe="mf6" ): name = "p01" nlay, nrow, ncol = 1, 1, 101 @@ -242,9 +221,8 @@ def p01mf6( tdis_rc.append((perlen[i], nstp[i], tsmult[i])) ws = model_ws - exe_name = os.path.abspath(exe_name_mf6) sim = flopy.mf6.MFSimulation( - sim_name=name, version="mf6", exe_name=exe_name, sim_ws=ws + sim_name=name, version="mf6", exe_name=exe, sim_ws=ws ) from flopy.mf6.mfbase import VerbosityLevel @@ -481,8 +459,7 @@ def p01mf6( return sim, conc -def test_mt3dmsp01a(): - +def test_mt3dmsp01a(function_tmpdir, targets): longitudinal_dispersivity = 0.0 retardation = 1.0 decay_rate = 0.00 @@ -490,7 +467,8 @@ def test_mt3dmsp01a(): zeta = None prsity2 = None - mf6_ws = os.path.join(testdir, testgroup + "a") + mf6 = targets["mf6"] + mf6_ws = str(function_tmpdir / (testgroup + "a")) sim, conc_mf6 = p01mf6( mf6_ws, longitudinal_dispersivity, @@ -499,8 +477,11 @@ def test_mt3dmsp01a(): mixelm, zeta, prsity2, + exe=mf6 ) + mf2005 = targets["mf2005s"] + mt3dms = targets["mt3dms"] mt3d_ws = os.path.join(mf6_ws, "mt3d") mf, mt, conc_mt3d, cvt, mvt = p01mt3d( mt3d_ws, @@ -510,6 +491,8 @@ def test_mt3dmsp01a(): mixelm, zeta, prsity2, + mf2005s=mf2005, + mt3dms=mt3dms ) msg = f"concentrations not equal {conc_mt3d} {conc_mf6}" @@ -540,13 +523,8 @@ def test_mt3dmsp01a(): bobj.file.close() assert np.allclose(0.0, storage_sorbed), f"{storage_sorbed}" - if remove_files: - shutil.rmtree(mf6_ws) - return - - -def test_mt3dmsp01b(): +def test_mt3dmsp01b(function_tmpdir, targets): longitudinal_dispersivity = 10.0 retardation = 1.0 decay_rate = 0.00 @@ -554,7 +532,8 @@ def test_mt3dmsp01b(): zeta = None prsity2 = None - mf6_ws = os.path.join(testdir, testgroup + "b") + mf6 = targets["mf6"] + mf6_ws = str(function_tmpdir / (testgroup + "b")) sim, conc_mf6 = p01mf6( mf6_ws, longitudinal_dispersivity, @@ -563,8 +542,11 @@ def test_mt3dmsp01b(): mixelm, zeta, prsity2, + exe=mf6 ) + mf2005 = targets["mf2005s"] + mt3dms = targets["mt3dms"] mt3d_ws = os.path.join(mf6_ws, "mt3d") mf, mt, conc_mt3d, cvt, mvt = p01mt3d( mt3d_ws, @@ -574,17 +556,15 @@ def test_mt3dmsp01b(): mixelm, zeta, prsity2, + mf2005s=mf2005, + mt3dms=mt3dms ) msg = f"concentrations not equal {conc_mt3d} {conc_mf6}" assert np.allclose(conc_mt3d, conc_mf6, atol=1e-4), msg - if remove_files: - shutil.rmtree(mf6_ws) - return -def test_mt3dmsp01c(): - +def test_mt3dmsp01c(function_tmpdir, targets): longitudinal_dispersivity = 10.0 retardation = 1.5 decay_rate = 0.00 @@ -592,7 +572,8 @@ def test_mt3dmsp01c(): zeta = None prsity2 = None - mf6_ws = os.path.join(testdir, testgroup + "c") + mf6 = targets["mf6"] + mf6_ws = str(function_tmpdir / (testgroup + "c")) sim, conc_mf6 = p01mf6( mf6_ws, longitudinal_dispersivity, @@ -601,8 +582,11 @@ def test_mt3dmsp01c(): mixelm, zeta, prsity2, + exe=mf6 ) + mf2005 = targets["mf2005s"] + mt3dms = targets["mt3dms"] mt3d_ws = os.path.join(mf6_ws, "mt3d") mf, mt, conc_mt3d, cvt, mvt = p01mt3d( mt3d_ws, @@ -612,17 +596,15 @@ def test_mt3dmsp01c(): mixelm, zeta, prsity2, + mf2005s=mf2005, + mt3dms=mt3dms ) msg = f"concentrations not equal {conc_mt3d} {conc_mf6}" assert np.allclose(conc_mt3d, conc_mf6, atol=1e-4), msg - if remove_files: - shutil.rmtree(mf6_ws) - return - -def test_mt3dmsp01d(): +def test_mt3dmsp01d(function_tmpdir, targets): longitudinal_dispersivity = 10.0 retardation = 1.5 decay_rate = 0.002 @@ -630,7 +612,8 @@ def test_mt3dmsp01d(): zeta = None prsity2 = None - mf6_ws = os.path.join(testdir, testgroup + "d") + mf6 = targets["mf6"] + mf6_ws = str(function_tmpdir / (testgroup + "d")) sim, conc_mf6 = p01mf6( mf6_ws, longitudinal_dispersivity, @@ -639,8 +622,11 @@ def test_mt3dmsp01d(): mixelm, zeta, prsity2, + exe=mf6 ) + mf2005 = targets["mf2005s"] + mt3dms = targets["mt3dms"] mt3d_ws = os.path.join(mf6_ws, "mt3d") mf, mt, conc_mt3d, cvt, mvt = p01mt3d( mt3d_ws, @@ -650,17 +636,15 @@ def test_mt3dmsp01d(): mixelm, zeta, prsity2, + mf2005s=mf2005, + mt3dms=mt3dms ) msg = f"concentrations not equal {conc_mt3d} {conc_mf6}" assert np.allclose(conc_mt3d, conc_mf6, atol=1e-4), msg - if remove_files: - shutil.rmtree(mf6_ws) - return - -def test_mt3dmsp01e(): +def test_mt3dmsp01e(function_tmpdir, targets): longitudinal_dispersivity = 10.0 retardation = 1.5 decay_rate = 0.002 @@ -668,7 +652,8 @@ def test_mt3dmsp01e(): zeta = 0.1 prsity2 = 0.05 - mf6_ws = os.path.join(testdir, testgroup + "e") + mf6 = targets["mf6"] + mf6_ws = str(function_tmpdir / (testgroup + "e")) sim, conc_mf6 = p01mf6( mf6_ws, longitudinal_dispersivity, @@ -677,8 +662,11 @@ def test_mt3dmsp01e(): mixelm, zeta, prsity2, + exe=mf6 ) + mf2005 = targets["mf2005s"] + mt3dms = targets["mt3dms"] mt3d_ws = os.path.join(mf6_ws, "mt3d") mf, mt, conc_mt3d, cvt, mvt = p01mt3d( mt3d_ws, @@ -688,17 +676,15 @@ def test_mt3dmsp01e(): mixelm, zeta, prsity2, + mf2005s=mf2005, + mt3dms=mt3dms ) msg = f"concentrations not equal {conc_mt3d} {conc_mf6}" assert np.allclose(conc_mt3d, conc_mf6, atol=1e-1), msg - if remove_files: - shutil.rmtree(mf6_ws) - return -def test_mt3dmsp01f(): - +def test_mt3dmsp01f(function_tmpdir, targets): longitudinal_dispersivity = 10.0 retardation = 1.5 decay_rate = 0.002 @@ -706,7 +692,8 @@ def test_mt3dmsp01f(): zeta = 0.1 prsity2 = 0.05 - mf6_ws = os.path.join(testdir, testgroup + "f") + mf6 = targets["mf6"] + mf6_ws = str(function_tmpdir / (testgroup + "f")) sim, conc_mf6 = p01mf6( mf6_ws, longitudinal_dispersivity, @@ -716,8 +703,11 @@ def test_mt3dmsp01f(): zeta, prsity2, onelambda=True, + exe=mf6 ) + mf2005 = targets["mf2005s"] + mt3dms = targets["mt3dms"] mt3d_ws = os.path.join(mf6_ws, "mt3d") mf, mt, conc_mt3d, cvt, mvt = p01mt3d( mt3d_ws, @@ -727,17 +717,15 @@ def test_mt3dmsp01f(): mixelm, zeta, prsity2, + mf2005s=mf2005, + mt3dms=mt3dms ) msg = f"concentrations not equal {conc_mt3d} {conc_mf6}" assert np.allclose(conc_mt3d, conc_mf6, atol=1e-1), msg - if remove_files: - shutil.rmtree(mf6_ws) - return - -def test_mt3dmsp01g(): +def test_mt3dmsp01g(function_tmpdir, targets): longitudinal_dispersivity = 0.0 retardation = 1.0 decay_rate = -1.0 @@ -745,7 +733,8 @@ def test_mt3dmsp01g(): zeta = None prsity2 = None - mf6_ws = os.path.join(testdir, testgroup + "g") + mf6 = targets["mf6"] + mf6_ws = str(function_tmpdir / (testgroup + "g")) sim, conc_mf6 = p01mf6( mf6_ws, longitudinal_dispersivity, @@ -755,8 +744,11 @@ def test_mt3dmsp01g(): zeta, prsity2, zero_order_decay=True, + exe=mf6 ) + mf2005 = targets["mf2005s"] + mt3dms = targets["mt3dms"] mt3d_ws = os.path.join(mf6_ws, "mt3d") mf, mt, conc_mt3d, cvt, mvt = p01mt3d( mt3d_ws, @@ -768,22 +760,9 @@ def test_mt3dmsp01g(): prsity2, rc2=0.0, zero_order_decay=True, + mf2005s=mf2005, + mt3dms=mt3dms ) msg = f"concentrations not equal {conc_mt3d} {conc_mf6}" assert np.allclose(conc_mt3d, conc_mf6, atol=1.0e-4), msg - if remove_files: - shutil.rmtree(mf6_ws) - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - test_mt3dmsp01a() - test_mt3dmsp01b() - test_mt3dmsp01c() - test_mt3dmsp01d() - test_mt3dmsp01e() - test_mt3dmsp01f() - test_mt3dmsp01g() diff --git a/autotest/test_gwt_mvt01.py b/autotest/test_gwt_mvt01.py index eb69289bf9e..be06ddec839 100644 --- a/autotest/test_gwt_mvt01.py +++ b/autotest/test_gwt_mvt01.py @@ -5,26 +5,14 @@ # There is no flow between the stream and the aquifer. import os -import sys +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["mvt_01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) def build_model(idx, dir): @@ -497,7 +485,7 @@ def eval_results(sim): print("evaluating results...") # ensure lake concentrations were saved - name = ex[sim.idxsim] + name = sim.name gwtname = "gwt_" + name fname = gwtname + ".sft.bin" fname = os.path.join(sim.simpath, fname) @@ -558,39 +546,13 @@ def eval_results(sim): # uncomment when testing so files aren't deleted # assert False - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_results, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_results, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_results, idxsim=0), ws) diff --git a/autotest/test_gwt_mvt02.py b/autotest/test_gwt_mvt02.py index 573f4a098c2..ad5c7547685 100644 --- a/autotest/test_gwt_mvt02.py +++ b/autotest/test_gwt_mvt02.py @@ -5,26 +5,14 @@ # There is no flow between the stream and the aquifer. import os -import sys +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["mvt_02"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) def build_model(idx, dir): @@ -398,7 +386,7 @@ def build_model(idx, dir): def eval_results(sim): print("evaluating results...") - name = ex[sim.idxsim] + name = sim.name gwtname = "gwt_" + name # Load csv budget and make sure names are correct @@ -489,39 +477,13 @@ def eval_results(sim): # uncomment when testing so files aren't deleted # assert False - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_results, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_results, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_results, idxsim=0), ws) diff --git a/autotest/test_gwt_mvt02fmi.py b/autotest/test_gwt_mvt02fmi.py index 3147d066fa6..ff6516e89d5 100644 --- a/autotest/test_gwt_mvt02fmi.py +++ b/autotest/test_gwt_mvt02fmi.py @@ -5,35 +5,13 @@ # There is no flow between the stream and the aquifer. import os -import shutil +from os.path import join +import flopy import numpy as np -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -import targets -from framework import set_teardown_test - -exe_name_mf6 = targets.target_dict["mf6"] -exe_name_mf6 = os.path.abspath(exe_name_mf6) - -testdir = "./temp" testgroup = "mvt02fmi" -d = os.path.join(testdir, testgroup) -if os.path.isdir(d): - shutil.rmtree(d) - - ex = ["mvt02fmi"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) # parameters lx = 7.0 @@ -61,13 +39,12 @@ hclose, rclose, relax = 1e-8, 1e-6, 0.97 -def run_flow_model(): - +def run_flow_model(dir, exe): name = "flow" gwfname = name - wsf = os.path.join(testdir, testgroup, name) + wsf = join(dir, testgroup, name) sim = flopy.mf6.MFSimulation( - sim_name=name, sim_ws=wsf, exe_name=exe_name_mf6 + sim_name=name, sim_ws=wsf, exe_name=exe ) # create tdis package @@ -262,18 +239,15 @@ def run_flow_model(): errmsg = f"flow model did not terminate successfully\n{buff}" assert success, errmsg - return - - -def run_transport_model(): +def run_transport_model(dir, exe): name = "transport" gwtname = name - wst = os.path.join(testdir, testgroup, name) + wst = join(dir, testgroup, name) sim = flopy.mf6.MFSimulation( sim_name=name, version="mf6", - exe_name=exe_name_mf6, + exe_name=exe, sim_ws=wst, continue_=False, memory_print_option=["ALL"], @@ -496,24 +470,8 @@ def run_transport_model(): # uncomment when testing so files aren't deleted # assert False - return - - -def test_mvt02fmi(): - run_flow_model() - run_transport_model() - d = os.path.join(testdir, testgroup) - - teardowntest = set_teardown_test() - if teardowntest: - if os.path.isdir(d): - shutil.rmtree(d) - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - # run tests - test_mvt02fmi() +def test_mvt02fmi(function_tmpdir, targets): + mf6 = targets.mf6 + run_flow_model(str(function_tmpdir), mf6) + run_transport_model(str(function_tmpdir), mf6) diff --git a/autotest/test_gwt_mwt01.py b/autotest/test_gwt_mwt01.py index 971aa819f63..c27ed21c2dc 100644 --- a/autotest/test_gwt_mwt01.py +++ b/autotest/test_gwt_mwt01.py @@ -4,26 +4,14 @@ # flows into the aquifer. import os -import sys +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["mwt_01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) def build_model(idx, dir): @@ -320,8 +308,8 @@ def build_model(idx, dir): def check_obs(sim): print("checking obs...") - name = ex[sim.idxsim] - ws = exdirs[sim.idxsim] + name = sim.name + ws = sim.simpath sim = flopy.mf6.MFSimulation.load(sim_ws=ws) gwfname = "gwf_" + name gwtname = "gwt_" + name @@ -385,14 +373,13 @@ def check_obs(sim): ) assert success, "One or more MWT obs checks did not pass" - return def eval_results(sim): print("evaluating results...") # ensure mwt concentrations were saved - name = ex[sim.idxsim] + name = sim.name gwtname = "gwt_" + name fname = gwtname + ".mwt.bin" fname = os.path.join(sim.simpath, fname) @@ -405,39 +392,13 @@ def eval_results(sim): check_obs(sim) - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_results, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_results, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_results, idxsim=idx), ws) diff --git a/autotest/test_gwt_mwt02.py b/autotest/test_gwt_mwt02.py index f91f2a92c6f..e0bbebd7265 100644 --- a/autotest/test_gwt_mwt02.py +++ b/autotest/test_gwt_mwt02.py @@ -2,26 +2,14 @@ # information. import os -import sys +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["mwt_02"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) def build_model(idx, dir): @@ -406,8 +394,8 @@ def build_model(idx, dir): def make_plot(sim): print("making plots...") - name = ex[sim.idxsim] - ws = exdirs[sim.idxsim] + name = sim.name + ws = sim.simpath sim = flopy.mf6.MFSimulation.load(sim_ws=ws) gwfname = "gwf_" + name gwtname = "gwt_" + name @@ -489,39 +477,11 @@ def eval_results(sim): # uncomment when testing # assert False - return - - -# - No need to change any code below -@pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), -) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_results, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_results, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - # run main routine - main() +@pytest.mark.slow +@pytest.mark.parametrize("name", ex) +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name, exes=targets, exfunc=eval_results, idxsim=0), ws) diff --git a/autotest/test_gwt_obs01.py b/autotest/test_gwt_obs01.py index 6dab2574d55..037b38d3e9f 100644 --- a/autotest/test_gwt_obs01.py +++ b/autotest/test_gwt_obs01.py @@ -6,28 +6,16 @@ import os +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = [ "gwt_obs01a", ] scheme = ["upstream"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" def build_model(idx, dir): @@ -257,25 +245,19 @@ def build_model(idx, dir): def eval_transport(sim): print("evaluating transport...") - name = ex[sim.idxsim] + name = sim.name gwtname = "gwt_" + name # MODFLOW 6 output control concentrations fpth = os.path.join(sim.simpath, f"{gwtname}.ucn") - try: - cobj = flopy.utils.HeadFile( - fpth, precision="double", text="CONCENTRATION" - ) - conc = cobj.get_alldata() - except: - assert False, f'could not load data from "{fpth}"' + cobj = flopy.utils.HeadFile( + fpth, precision="double", text="CONCENTRATION" + ) + conc = cobj.get_alldata() # MODFLOW 6 observation package concentrations fpth = os.path.join(sim.simpath, "conc_obs.csv") - try: - tc = np.genfromtxt(fpth, names=True, delimiter=",") - except: - assert False, f'could not load data from "{fpth}"' + tc = np.genfromtxt(fpth, names=True, delimiter=",") assert np.allclose( tc["1_1_10"], conc[:, 0, 0, 9] @@ -285,42 +267,13 @@ def eval_transport(sim): tc["1_1_50"], conc[:, 0, 0, 49] ), "obs concentrations do not match oc concentrations." - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=0), ws) diff --git a/autotest/test_gwt_prudic2004t2.py b/autotest/test_gwt_prudic2004t2.py index 2d1f2d411ee..8c12d0b9691 100644 --- a/autotest/test_gwt_prudic2004t2.py +++ b/autotest/test_gwt_prudic2004t2.py @@ -7,27 +7,17 @@ import os import sys +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from conftest import get_project_root_path +from harness import TestHarness, TestConfig ex = ["prudic2004t2"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) - -data_ws = "./data/prudic2004test2/" -fname = os.path.join(data_ws, "lakibd.dat") +data_path = get_project_root_path() / "autotest" / "data" +model_path = data_path / "prudic2004test2" +fname = str(model_path / "lakibd.dat") lakibd = np.loadtxt(fname, dtype=int) @@ -43,7 +33,7 @@ def build_model(idx, dir): exe_name="mf6", sim_ws=ws, continue_=False, - memory_print_option="ALL", + memory_print_option='ALL', ) # number of time steps for period 2 are reduced from 12 * 25 to 25 in @@ -84,10 +74,10 @@ def build_model(idx, dir): delr = 405.665 delc = 403.717 top = 100.0 - fname = os.path.join(data_ws, "bot1.dat") + fname = str(model_path / "bot1.dat") bot0 = np.loadtxt(fname) botm = [bot0] + [bot0 - (15.0 * k) for k in range(1, nlay)] - fname = os.path.join(data_ws, "idomain1.dat") + fname = str(model_path / "idomain1.dat") idomain0 = np.loadtxt(fname, dtype=int) idomain = nlay * [idomain0] dis = flopy.mf6.ModflowGwfdis( @@ -100,7 +90,6 @@ def build_model(idx, dir): top=top, botm=botm, idomain=idomain, - length_units="feet", ) idomain = dis.idomain.array @@ -146,7 +135,7 @@ def build_model(idx, dir): ) chdlist = [] - fname = os.path.join(data_ws, "chd.dat") + fname = str(model_path / "chd.dat") for line in open(fname, "r").readlines(): ll = line.strip().split() if len(ll) == 4: @@ -166,7 +155,7 @@ def build_model(idx, dir): ) rivlist = [] - fname = os.path.join(data_ws, "riv.dat") + fname = str(model_path / "riv.dat") for line in open(fname, "r").readlines(): ll = line.strip().split() if len(ll) == 7: @@ -189,7 +178,7 @@ def build_model(idx, dir): )[0] for i, t in enumerate(rivlist): rivra[i] = tuple(t) - sfrpd = np.genfromtxt(data_ws + "sfr-packagedata.dat", names=True) + sfrpd = np.genfromtxt(model_path / "sfr-packagedata.dat", names=True) sfrpackagedata = flopy.mf6.ModflowGwfsfr.packagedata.empty( gwf, boundnames=True, maxbound=sfrpd.shape[0] ) @@ -200,7 +189,7 @@ def build_model(idx, dir): if name in sfrpd.dtype.names: sfrpackagedata[name] = sfrpd[name] sfrpackagedata["boundname"] = rivra["boundname"] - with open(data_ws + "sfr-connectiondata.dat") as f: + with open(model_path / "sfr-connectiondata.dat") as f: lines = f.readlines() sfrconnectiondata = [] for line in lines: @@ -327,16 +316,13 @@ def build_model(idx, dir): [1, 35.2, nlakecon[1], "lake2"], ] # - outlets = [ - [0, 0, -1, "MANNING", 44.5, 3.36493214532915, 0.03, 0.2187500e-02] - ] + outlets = [[0, 0, -1, "MANNING", 44.5, 5.000000, 0.03, 0.2187500e-02]] lake_on = True if lake_on: lak = flopy.mf6.ModflowGwflak( gwf, time_conversion=86400.000, - length_conversion=3.28081, print_stage=True, print_flows=True, stage_filerecord=gwfname + ".lak.bin", @@ -599,8 +585,8 @@ def build_model(idx, dir): def make_concentration_vs_time(sim): print("making plot of concentration versus time...") - name = ex[sim.idxsim] - ws = exdirs[sim.idxsim] + name = sim.name + ws = sim.simpath sim = flopy.mf6.MFSimulation.load(sim_ws=ws) gwfname = "gwf_" + name gwtname = "gwt_" + name @@ -658,8 +644,8 @@ def make_concentration_map(sim): 500, ] - name = ex[sim.idxsim] - ws = exdirs[sim.idxsim] + name = sim.name + ws = sim.simpath simfp = flopy.mf6.MFSimulation.load(sim_ws=ws) gwfname = "gwf_" + name gwtname = "gwt_" + name @@ -697,8 +683,8 @@ def make_concentration_map(sim): def check_obs(sim): print("checking obs...") - name = ex[sim.idxsim] - ws = exdirs[sim.idxsim] + name = sim.name + ws = sim.simpath sim = flopy.mf6.MFSimulation.load(sim_ws=ws) gwfname = "gwf_" + name gwtname = "gwt_" + name @@ -843,8 +829,8 @@ def eval_results(sim): make_concentration_map(sim) # ensure concentrations were saved - ws = exdirs[sim.idxsim] - name = ex[sim.idxsim] + ws = sim.simpath + name = sim.name gwtname = "gwt_" + name check_obs(sim) @@ -984,39 +970,14 @@ def eval_results(sim): # uncomment when testing # assert False - return - -# - No need to change any code below +@pytest.mark.slow @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_results, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_results, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_results, idxsim=idx), ws) diff --git a/autotest/test_gwt_prudic2004t2fmi.py b/autotest/test_gwt_prudic2004t2fmi.py index 00551a1d3a6..a2ddfa5c38a 100644 --- a/autotest/test_gwt_prudic2004t2fmi.py +++ b/autotest/test_gwt_prudic2004t2fmi.py @@ -1,40 +1,17 @@ # tests to ability to run flow model first followed by transport model import os -import shutil +from os.path import join +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) +from conftest import get_project_root_path -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - - -import targets -from framework import set_teardown_test - -exe_name_mf6 = targets.target_dict["mf6"] -exe_name_mf6 = os.path.abspath(exe_name_mf6) - -data_ws = os.path.abspath("./data/prudic2004test2/") -testdir = "./temp" +data_path = get_project_root_path() / "autotest" / "data" +model_path = str(data_path / "prudic2004test2") testgroup = "prudic2004t2fmi" -d = os.path.join(testdir, testgroup) -if os.path.isdir(d): - shutil.rmtree(d) nlay = 8 nrow = 36 @@ -42,21 +19,21 @@ delr = 405.665 delc = 403.717 top = 100.0 -fname = os.path.join(data_ws, "bot1.dat") +fname = os.path.join(model_path, "bot1.dat") bot0 = np.loadtxt(fname) botm = [bot0] + [bot0 - (15.0 * k) for k in range(1, nlay)] -fname = os.path.join(data_ws, "idomain1.dat") +fname = os.path.join(model_path, "idomain1.dat") idomain0 = np.loadtxt(fname, dtype=int) idomain = nlay * [idomain0] -def run_flow_model(): +def run_flow_model(dir, exe): global idomain name = "flow" gwfname = name - wsf = os.path.join(testdir, testgroup, name) + wsf = join(dir, testgroup, name) sim = flopy.mf6.MFSimulation( - sim_name=name, sim_ws=wsf, exe_name=exe_name_mf6 + sim_name=name, sim_ws=wsf, exe_name=exe ) tdis_rc = [(1.0, 1, 1.0), (365.25 * 25, 1, 1.0)] nper = len(tdis_rc) @@ -144,7 +121,7 @@ def run_flow_model(): ) chdlist = [] - fname = os.path.join(data_ws, "chd.dat") + fname = os.path.join(model_path, "chd.dat") for line in open(fname, "r").readlines(): ll = line.strip().split() if len(ll) == 4: @@ -164,7 +141,7 @@ def run_flow_model(): ) rivlist = [] - fname = os.path.join(data_ws, "riv.dat") + fname = os.path.join(model_path, "riv.dat") for line in open(fname, "r").readlines(): ll = line.strip().split() if len(ll) == 7: @@ -187,7 +164,7 @@ def run_flow_model(): )[0] for i, t in enumerate(rivlist): rivra[i] = tuple(t) - fname = os.path.join(data_ws, "sfr-packagedata.dat") + fname = os.path.join(model_path, "sfr-packagedata.dat") sfrpd = np.genfromtxt(fname, names=True) sfrpackagedata = flopy.mf6.ModflowGwfsfr.packagedata.empty( gwf, boundnames=True, maxbound=sfrpd.shape[0] @@ -199,7 +176,7 @@ def run_flow_model(): if name in sfrpd.dtype.names: sfrpackagedata[name] = sfrpd[name] sfrpackagedata["boundname"] = rivra["boundname"] - fname = os.path.join(data_ws, "sfr-connectiondata.dat") + fname = os.path.join(model_path, "sfr-connectiondata.dat") with open(fname) as f: lines = f.readlines() sfrconnectiondata = [] @@ -243,7 +220,7 @@ def run_flow_model(): observations=sfr_obs, ) - fname = os.path.join(data_ws, "lakibd.dat") + fname = os.path.join(model_path, "lakibd.dat") lakibd = np.loadtxt(fname, dtype=int) lakeconnectiondata = [] nlakecon = [0, 0] @@ -354,16 +331,13 @@ def run_flow_model(): [1, 35.2, nlakecon[1], "lake2"], ] # - outlets = [ - [0, 0, -1, "MANNING", 44.5, 3.36493214532915, 0.03, 0.2187500e-02] - ] + outlets = [[0, 0, -1, "MANNING", 44.5, 5.000000, 0.03, 0.2187500e-02]] lake_on = True if lake_on: lak = flopy.mf6.ModflowGwflak( gwf, time_conversion=86400.000, - length_conversion=3.28081, print_stage=True, print_flows=True, stage_filerecord=gwfname + ".lak.bin", @@ -458,17 +432,15 @@ def run_flow_model(): for node, node2, q in d: print(p1, node, p2, node2, q) - return - -def run_transport_model(): +def run_transport_model(dir, exe): name = "transport" gwtname = name - wst = os.path.join(testdir, testgroup, name) + wst = join(dir, testgroup, name) sim = flopy.mf6.MFSimulation( sim_name=name, version="mf6", - exe_name=exe_name_mf6, + exe_name=exe, sim_ws=wst, continue_=False, ) @@ -515,7 +487,6 @@ def run_transport_model(): top=top, botm=botm, idomain=idomain, - length_units="feet", ) ic = flopy.mf6.ModflowGwtic(gwt, strt=0.0) sto = flopy.mf6.ModflowGwtmst(gwt, porosity=0.3) @@ -811,23 +782,10 @@ def run_transport_model(): for rate1, rate2 in zip(csvra[name1], lstra[name2]): print(rate1, rate2) assert success_all, f"Comparisons failed for {failed_list}" - return - - -def test_prudic2004t2fmi(): - run_flow_model() - run_transport_model() - d = os.path.join(testdir, testgroup) - teardowntest = set_teardown_test() - if teardowntest: - if os.path.isdir(d): - shutil.rmtree(d) - return - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - # run tests - test_prudic2004t2fmi() +@pytest.mark.slow +def test_prudic2004t2fmi(function_tmpdir, targets): + mf6 = targets.mf6 + run_flow_model(str(function_tmpdir), mf6) + run_transport_model(str(function_tmpdir), mf6) diff --git a/autotest/test_gwt_prudic2004t2fmiats.py b/autotest/test_gwt_prudic2004t2fmiats.py index 68b1651eec9..0a0fa78d1d1 100644 --- a/autotest/test_gwt_prudic2004t2fmiats.py +++ b/autotest/test_gwt_prudic2004t2fmiats.py @@ -5,40 +5,17 @@ # failure occurs. import os -import shutil +from os.path import join +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) +from conftest import get_project_root_path -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - - -import targets -from framework import set_teardown_test - -exe_name_mf6 = targets.target_dict["mf6"] -exe_name_mf6 = os.path.abspath(exe_name_mf6) - -data_ws = os.path.abspath("./data/prudic2004test2/") -testdir = "./temp" +data_path = get_project_root_path() / "autotest" / "data" +model_path = str(data_path / "prudic2004test2") testgroup = "prudic2004t2fmiats" -d = os.path.join(testdir, testgroup) -if os.path.isdir(d): - shutil.rmtree(d) nlay = 8 nrow = 36 @@ -46,21 +23,21 @@ delr = 405.665 delc = 403.717 top = 100.0 -fname = os.path.join(data_ws, "bot1.dat") +fname = os.path.join(model_path, "bot1.dat") bot0 = np.loadtxt(fname) botm = [bot0] + [bot0 - (15.0 * k) for k in range(1, nlay)] -fname = os.path.join(data_ws, "idomain1.dat") +fname = os.path.join(model_path, "idomain1.dat") idomain0 = np.loadtxt(fname, dtype=int) idomain = nlay * [idomain0] -def run_flow_model(): +def run_flow_model(dir, exe): global idomain name = "flow" gwfname = name - wsf = os.path.join(testdir, testgroup, name) + wsf = join(dir, testgroup, name) sim = flopy.mf6.MFSimulation( - sim_name=name, sim_ws=wsf, exe_name=exe_name_mf6 + sim_name=name, sim_ws=wsf, exe_name=exe ) tdis_rc = [(1.0, 1, 1.0), (365.25 * 25, 1, 1.0)] nper = len(tdis_rc) @@ -102,7 +79,6 @@ def run_flow_model(): top=top, botm=botm, idomain=idomain, - length_units="feet", ) idomain = dis.idomain.array @@ -149,7 +125,7 @@ def run_flow_model(): ) chdlist = [] - fname = os.path.join(data_ws, "chd.dat") + fname = os.path.join(model_path, "chd.dat") for line in open(fname, "r").readlines(): ll = line.strip().split() if len(ll) == 4: @@ -169,7 +145,7 @@ def run_flow_model(): ) rivlist = [] - fname = os.path.join(data_ws, "riv.dat") + fname = os.path.join(model_path, "riv.dat") for line in open(fname, "r").readlines(): ll = line.strip().split() if len(ll) == 7: @@ -192,7 +168,7 @@ def run_flow_model(): )[0] for i, t in enumerate(rivlist): rivra[i] = tuple(t) - fname = os.path.join(data_ws, "sfr-packagedata.dat") + fname = os.path.join(model_path, "sfr-packagedata.dat") sfrpd = np.genfromtxt(fname, names=True) sfrpackagedata = flopy.mf6.ModflowGwfsfr.packagedata.empty( gwf, boundnames=True, maxbound=sfrpd.shape[0] @@ -204,7 +180,7 @@ def run_flow_model(): if name in sfrpd.dtype.names: sfrpackagedata[name] = sfrpd[name] sfrpackagedata["boundname"] = rivra["boundname"] - fname = os.path.join(data_ws, "sfr-connectiondata.dat") + fname = os.path.join(model_path, "sfr-connectiondata.dat") with open(fname) as f: lines = f.readlines() sfrconnectiondata = [] @@ -248,7 +224,7 @@ def run_flow_model(): observations=sfr_obs, ) - fname = os.path.join(data_ws, "lakibd.dat") + fname = os.path.join(model_path, "lakibd.dat") lakibd = np.loadtxt(fname, dtype=int) lakeconnectiondata = [] nlakecon = [0, 0] @@ -359,16 +335,13 @@ def run_flow_model(): [1, 35.2, nlakecon[1], "lake2"], ] # - outlets = [ - [0, 0, -1, "MANNING", 44.5, 3.36493214532915, 0.03, 0.2187500e-02] - ] + outlets = [[0, 0, -1, "MANNING", 44.5, 5.000000, 0.03, 0.2187500e-02]] lake_on = True if lake_on: lak = flopy.mf6.ModflowGwflak( gwf, time_conversion=86400.000, - length_conversion=3.28081, print_stage=True, print_flows=True, stage_filerecord=gwfname + ".lak.bin", @@ -454,17 +427,15 @@ def run_flow_model(): for node, node2, q in d: print(p1, node, p2, node2, q) - return - -def run_transport_model(): +def run_transport_model(dir, exe): name = "transport" gwtname = name - wst = os.path.join(testdir, testgroup, name) + wst = join(dir, testgroup, name) sim = flopy.mf6.MFSimulation( sim_name=name, version="mf6", - exe_name=exe_name_mf6, + exe_name=exe, sim_ws=wst, continue_=False, ) @@ -879,23 +850,9 @@ def run_transport_model(): all_found ), "One or more required text strings not found in mfsim.lst" - return - - -def test_prudic2004t2fmiats(): - run_flow_model() - run_transport_model() - d = os.path.join(testdir, testgroup) - teardowntest = set_teardown_test() - if teardowntest: - if os.path.isdir(d): - shutil.rmtree(d) - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - # run tests - test_prudic2004t2fmiats() +@pytest.mark.slow +def test_prudic2004t2fmiats(function_tmpdir, targets): + mf6 = targets.mf6 + run_flow_model(dir=str(function_tmpdir), exe=mf6) + run_transport_model(dir=str(function_tmpdir), exe=mf6) diff --git a/autotest/test_gwt_prudic2004t2gwtgwt.py b/autotest/test_gwt_prudic2004t2gwtgwt.py index 022a9ddc17d..d8b2505c748 100644 --- a/autotest/test_gwt_prudic2004t2gwtgwt.py +++ b/autotest/test_gwt_prudic2004t2gwtgwt.py @@ -7,26 +7,16 @@ import os import sys +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) +from conftest import get_project_root_path +from harness import TestHarness, TestConfig -from framework import testing_framework -from simulation import Simulation - -data_ws = "./data/prudic2004test2gwtgwt/" +data_path = get_project_root_path() / "autotest" / "data" +model_path = str(data_path / "prudic2004test2gwtgwt") ex = ["prudic2004t2gwtgwt"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) - gwfnames = ["flow1", "flow2"] gwtnames = ["transport1", "transport2"] @@ -37,7 +27,7 @@ delr = 405.665 delc = 403.717 top = 100.0 -fname = os.path.join(data_ws, "bot1.dat") +fname = os.path.join(model_path, "bot1.dat") bot0 = np.loadtxt(fname) botm = [bot0] + [bot0 - (15.0 * k) for k in range(1, nlay)] @@ -57,12 +47,12 @@ across_model_mvt_on = True and across_model_mvr_on # setup idomain -fname = os.path.join(data_ws, "idomain1.dat") +fname = os.path.join(model_path, "idomain1.dat") idomain0 = np.loadtxt(fname, dtype=int) idomain = nlay * [idomain0] idomain = np.array(idomain) -fname = os.path.join(data_ws, "lakibd.dat") +fname = os.path.join(model_path, "lakibd.dat") lakibd = np.loadtxt(fname, dtype=int) @@ -353,7 +343,7 @@ def build_gwfgwt_combo( else: fname = "chd_south.dat" chdlist = [] - fname = os.path.join(data_ws, fname) + fname = os.path.join(model_path, fname) print(f"Setting CHD information from: {fname}") for line in open(fname, "r").readlines(): ll = line.strip().split() @@ -383,10 +373,10 @@ def build_gwfgwt_combo( [0, "inflow", 8640.0], ] } - fname = os.path.join(data_ws, f"sfr-packdata-{isfrseg}.dat") + fname = os.path.join(model_path, f"sfr-packdata-{isfrseg}.dat") sfrpd = sfr_packagedata_to_list(fname, gwf) nreaches = len(sfrpd) - fname = os.path.join(data_ws, f"sfr-conndata-{isfrseg}.dat") + fname = os.path.join(model_path, f"sfr-conndata-{isfrseg}.dat") sfrcd = sfr_connectiondata_to_list(fname) print(f"Setting nreaches to {nreaches}") sfr = flopy.mf6.ModflowGwfsfr( @@ -504,9 +494,7 @@ def build_gwfgwt_combo( if icombo == 1: lakpackagedata = [[0, 44.0, nlakecon[0], "lake1"]] # - outlets = [ - [0, 0, -1, "MANNING", 44.5, 3.36493214532915, 0.03, 0.2187500e-02] - ] + outlets = [[0, 0, -1, "MANNING", 44.5, 5.000000, 0.03, 0.2187500e-02]] noutlets = 1 elif icombo == 2: lakpackagedata = [[0, 35.2, nlakecon[0], "lake2"]] @@ -521,7 +509,6 @@ def build_gwfgwt_combo( lak = flopy.mf6.ModflowGwflak( gwf, time_conversion=86400.000, - length_conversion=3.28081, print_stage=True, print_flows=True, stage_filerecord=gwfname + ".lak.bin", @@ -892,18 +879,16 @@ def make_concentration_map(sim, ws): print(f"Creating {fname}") plt.savefig(fname) - return - def eval_results(sim): print("evaluating results...") # these answer files are results from autotest/prudic2004test2 - fname = os.path.join(data_ws, "result_conc_lak1.txt") + fname = os.path.join(model_path, "result_conc_lak1.txt") ans_lak1 = np.loadtxt(fname) - fname = os.path.join(data_ws, "result_conc_sfr3.txt") + fname = os.path.join(model_path, "result_conc_sfr3.txt") ans_sfr3 = np.loadtxt(fname) - fname = os.path.join(data_ws, "result_conc_sfr4.txt") + fname = os.path.join(model_path, "result_conc_sfr4.txt") ans_sfr4 = np.loadtxt(fname) makeplot = False @@ -911,7 +896,7 @@ def eval_results(sim): if arg.lower() == "--makeplot": makeplot = True - ws = exdirs[sim.idxsim] + ws = sim.simpath simfp = flopy.mf6.MFSimulation.load(sim_ws=ws, strict=False) if makeplot: @@ -921,7 +906,7 @@ def eval_results(sim): make_concentration_map(simfp, ws) # ensure concentrations were saved - ws = exdirs[sim.idxsim] + ws = sim.simpath gwfname = gwfnames[0] gwtname = gwtnames[0] @@ -975,39 +960,14 @@ def eval_results(sim): # uncomment when testing # assert False - return - -# - No need to change any code below +@pytest.mark.slow @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_results, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_results, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_results, idxsim=idx), ws) diff --git a/autotest/test_gwt_sft01.py b/autotest/test_gwt_sft01.py index 81e75c0bd65..a4f04674448 100644 --- a/autotest/test_gwt_sft01.py +++ b/autotest/test_gwt_sft01.py @@ -6,26 +6,14 @@ # There is no flow between the stream and the aquifer. import os -import sys +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["sft_01"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) def build_model(idx, dir): @@ -381,7 +369,7 @@ def eval_results(sim): print("evaluating results...") # ensure lake concentrations were saved - name = ex[sim.idxsim] + name = sim.name gwtname = "gwt_" + name fname = gwtname + ".sft.bin" fname = os.path.join(sim.simpath, fname) @@ -436,39 +424,13 @@ def eval_results(sim): # uncomment when testing # assert False - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_results, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_results, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_results, idxsim=0), ws) diff --git a/autotest/test_gwt_sft01gwtgwt.py b/autotest/test_gwt_sft01gwtgwt.py index 005374a5934..33842b84290 100644 --- a/autotest/test_gwt_sft01gwtgwt.py +++ b/autotest/test_gwt_sft01gwtgwt.py @@ -16,27 +16,13 @@ # gwt 1 2 3 4 5 6 7 gwtgwt => 1 2 3 4 5 6 7 -import os -import sys - +import flopy import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["sft01gwtgwt"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) # properties for each model combination lx = 7.0 @@ -499,7 +485,7 @@ def eval_results(sim): print("evaluating results...") # load the simulations - ws = exdirs[sim.idxsim] + ws = sim.simpath sim = flopy.mf6.MFSimulation.load(sim_ws=ws) # construct head and conc for combined models @@ -526,39 +512,13 @@ def eval_results(sim): conc, sfrconc ), "aquifer concentration does not equal sfr concentration" - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_results, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_results, idxsim=idx) - test.run_mf6(sim) - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_results, idxsim=idx), ws) diff --git a/autotest/test_gwt_src01.py b/autotest/test_gwt_src01.py index 4121f4fb4dc..ff919cb7403 100644 --- a/autotest/test_gwt_src01.py +++ b/autotest/test_gwt_src01.py @@ -7,36 +7,15 @@ """ import os -import sys +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["src01a"] xt3d = [False] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" def build_model(idx, dir): @@ -262,17 +241,14 @@ def build_model(idx, dir): def eval_transport(sim): print("evaluating transport...") - name = ex[sim.idxsim] + name = sim.name gwtname = "gwt_" + name fpth = os.path.join(sim.simpath, f"{gwtname}.ucn") - try: - cobj = flopy.utils.HeadFile( - fpth, precision="double", text="CONCENTRATION" - ) - conc = cobj.get_data() - except: - assert False, f'could not load data from "{fpth}"' + cobj = flopy.utils.HeadFile( + fpth, precision="double", text="CONCENTRATION" + ) + conc = cobj.get_data() # This is the answer to this problem. These concentrations are for # steady state and calculated from F = D * (c1 - c2) / L @@ -281,42 +257,13 @@ def eval_transport(sim): cres, conc ), "simulated concentrations do not match with known solution." - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=0), ws) diff --git a/autotest/test_gwt_ssm01fmi.py b/autotest/test_gwt_ssm01fmi.py index 7c3c83aa145..e4ef62b7d64 100644 --- a/autotest/test_gwt_ssm01fmi.py +++ b/autotest/test_gwt_ssm01fmi.py @@ -4,38 +4,12 @@ # be 100. import os -import shutil +from os.path import join +import flopy import numpy as np -import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - - -import targets - -exe_name_mf6 = targets.target_dict["mf6"] -exe_name_mf6 = os.path.abspath(exe_name_mf6) - -testdir = "./temp" testgroup = "ssm01" -d = os.path.join(testdir, testgroup) -if os.path.isdir(d): - shutil.rmtree(d) nlay = 1 nrow = 10 @@ -46,13 +20,13 @@ botm = 0.0 -def run_flow_model(): +def run_flow_model(dir, exe): global idomain name = "flow" gwfname = name - wsf = os.path.join(testdir, testgroup, name) + wsf = join(dir, testgroup, name) sim = flopy.mf6.MFSimulation( - sim_name=name, sim_ws=wsf, exe_name=exe_name_mf6 + sim_name=name, sim_ws=wsf, exe_name=exe ) tdis_rc = [(100.0, 1, 1.0), (100.0, 1, 1.0)] nper = len(tdis_rc) @@ -194,17 +168,15 @@ def run_flow_model(): errmsg = f"flow model did not terminate successfully\n{buff}" assert success, errmsg - return - -def run_transport_model(): +def run_transport_model(dir, exe): name = "transport" gwtname = name - wst = os.path.join(testdir, testgroup, name) + wst = join(dir, testgroup, name) sim = flopy.mf6.MFSimulation( sim_name=name, version="mf6", - exe_name=exe_name_mf6, + exe_name=exe, sim_ws=wst, continue_=False, ) @@ -338,21 +310,8 @@ def run_transport_model(): ) assert np.all(simulated_concentration == 100.0), errmsg - return - - -def test_ssm01fmi(): - run_flow_model() - run_transport_model() - d = os.path.join(testdir, testgroup) - if os.path.isdir(d): - shutil.rmtree(d) - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - # run tests - test_ssm01fmi() +def test_ssm01fmi(function_tmpdir, targets): + mf6 = targets.mf6 + run_flow_model(str(function_tmpdir), mf6) + run_transport_model(str(function_tmpdir), mf6) diff --git a/autotest/test_gwt_ssm02.py b/autotest/test_gwt_ssm02.py index b746e5a07b7..b3ab45d07ac 100644 --- a/autotest/test_gwt_ssm02.py +++ b/autotest/test_gwt_ssm02.py @@ -9,35 +9,16 @@ import os +import flopy import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["ssm02"] laytyp = [1] ss = [1.0e-10] sy = [0.1] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) nlay, nrow, ncol = 1, 1, 1 @@ -239,25 +220,19 @@ def build_model(idx, dir): def eval_transport(sim): print("evaluating transport...") - name = ex[sim.idxsim] + name = sim.name gwtname = "gwt_" + name gwfname = "gwf_" + name fpth = os.path.join(sim.simpath, f"{gwfname}.hds") - try: - hobj = flopy.utils.HeadFile(fpth, precision="double") - head = hobj.get_alldata().flatten() - except: - assert False, f'could not load data from "{fpth}"' + hobj = flopy.utils.HeadFile(fpth, precision="double") + head = hobj.get_alldata().flatten() fpth = os.path.join(sim.simpath, f"{gwtname}.ucn") - try: - cobj = flopy.utils.HeadFile( - fpth, precision="double", text="CONCENTRATION" - ) - conc = cobj.get_alldata().flatten() - except: - assert False, f'could not load data from "{fpth}"' + cobj = flopy.utils.HeadFile( + fpth, precision="double", text="CONCENTRATION" + ) + conc = cobj.get_alldata().flatten() # calculations times = hobj.get_times() @@ -278,42 +253,13 @@ def eval_transport(sim): assert np.allclose(c, conc_calc, atol=0.001), msg vold = v - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=0), ws) diff --git a/autotest/test_gwt_ssm03.py b/autotest/test_gwt_ssm03.py index d94d3f91ab6..0304a207f9d 100644 --- a/autotest/test_gwt_ssm03.py +++ b/autotest/test_gwt_ssm03.py @@ -10,21 +10,11 @@ import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) +import flopy -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["ssm03"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) def build_model(idx, dir): @@ -243,28 +233,22 @@ def build_model(idx, dir): def eval_transport(sim): print("evaluating transport...") - name = ex[sim.idxsim] + name = sim.name gwtname = "gwt_" + name # load concentration file fpth = os.path.join(sim.simpath, f"{gwtname}.ucn") - try: - cobj = flopy.utils.HeadFile( - fpth, precision="double", text="CONCENTRATION" - ) - conc = cobj.get_data() - except: - assert False, f'could not load data from "{fpth}"' + cobj = flopy.utils.HeadFile( + fpth, precision="double", text="CONCENTRATION" + ) + conc = cobj.get_data() # load transport budget file fpth = os.path.join(sim.simpath, f"{gwtname}.cbc") - try: - bobj = flopy.utils.CellBudgetFile( - fpth, - precision="double", - ) - except: - assert False, f'could not load data from "{fpth}"' + bobj = flopy.utils.CellBudgetFile( + fpth, + precision="double", + ) ssmbudall = bobj.get_data(text="SOURCE-SINK MIX") for ssmbud in ssmbudall: @@ -279,42 +263,13 @@ def eval_transport(sim): assert node2 == 1, "node2 location for chd must be 1 (first chd)" assert q < 0.0, "mass flux for chd must be less than zero" - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=0), ws) diff --git a/autotest/test_gwt_ssm04.py b/autotest/test_gwt_ssm04.py index 84485de916e..b90bfd23467 100644 --- a/autotest/test_gwt_ssm04.py +++ b/autotest/test_gwt_ssm04.py @@ -16,21 +16,11 @@ import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) +import flopy -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["ssm04"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) nlay, nrow, ncol = 3, 5, 5 idomain_lay0 = [ @@ -413,28 +403,22 @@ def build_model(idx, dir): def eval_transport(sim): print("evaluating transport...") - name = ex[sim.idxsim] + name = sim.name gwtname = "gwt_" + name # load concentration file fpth = os.path.join(sim.simpath, f"{gwtname}.ucn") - try: - cobj = flopy.utils.HeadFile( - fpth, precision="double", text="CONCENTRATION" - ) - conc = cobj.get_data() - except: - assert False, f'could not load data from "{fpth}"' + cobj = flopy.utils.HeadFile( + fpth, precision="double", text="CONCENTRATION" + ) + conc = cobj.get_data() # load transport budget file fpth = os.path.join(sim.simpath, f"{gwtname}.cbc") - try: - bobj = flopy.utils.CellBudgetFile( - fpth, - precision="double", - ) - except: - assert False, f'could not load data from "{fpth}"' + bobj = flopy.utils.CellBudgetFile( + fpth, + precision="double", + ) ssmbudall = bobj.get_data(text="SOURCE-SINK MIX") times = cobj.get_times() @@ -500,42 +484,13 @@ def eval_transport(sim): istart = istop - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=0), ws) diff --git a/autotest/test_gwt_ssm05.py b/autotest/test_gwt_ssm05.py index e6a84fd536d..14accbe1e27 100644 --- a/autotest/test_gwt_ssm05.py +++ b/autotest/test_gwt_ssm05.py @@ -10,21 +10,11 @@ import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) +import flopy -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig ex = ["ssm05"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) nlay, nrow, ncol = 3, 5, 5 idomain_lay0 = [ @@ -252,28 +242,22 @@ def build_model(idx, dir): def eval_transport(sim): print("evaluating transport...") - name = ex[sim.idxsim] + name = sim.name gwtname = "gwt_" + name # load concentration file fpth = os.path.join(sim.simpath, f"{gwtname}.ucn") - try: - cobj = flopy.utils.HeadFile( - fpth, precision="double", text="CONCENTRATION" - ) - conc = cobj.get_data() - except: - assert False, f'could not load data from "{fpth}"' + cobj = flopy.utils.HeadFile( + fpth, precision="double", text="CONCENTRATION" + ) + conc = cobj.get_data() # load transport budget file fpth = os.path.join(sim.simpath, f"{gwtname}.cbc") - try: - bobj = flopy.utils.CellBudgetFile( - fpth, - precision="double", - ) - except: - assert False, f'could not load data from "{fpth}"' + bobj = flopy.utils.CellBudgetFile( + fpth, + precision="double", + ) ssmbudall = bobj.get_data(text="SOURCE-SINK MIX") times = cobj.get_times() @@ -332,42 +316,13 @@ def eval_transport(sim): istart = istop - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the models - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_transport, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # build the models - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_transport, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_transport, idxsim=0), ws) diff --git a/autotest/test_gwt_ssm06.py b/autotest/test_gwt_ssm06.py index 4755fa610f9..c6eab560a71 100644 --- a/autotest/test_gwt_ssm06.py +++ b/autotest/test_gwt_ssm06.py @@ -2,38 +2,13 @@ # See test_gwt_ssm06fmi.py for additional detail on what this test is about. import os -import shutil import numpy as np -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) +import flopy -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -import targets - -exe_name_mf6 = targets.target_dict["mf6"] -exe_name_mf6 = os.path.abspath(exe_name_mf6) - -testdir = "./temp" testgroup = "ssm06" -d = os.path.join(testdir, testgroup) -if os.path.isdir(d): - shutil.rmtree(d) - nlay = 1 nrow = 10 @@ -66,12 +41,12 @@ ndv = 0 -def run_flw_and_trnprt_models(): +def run_flw_and_trnprt_models(dir, exe): global idomain gwfname = "gwf-" + testgroup - ws = os.path.join(testdir, testgroup) + ws = dir sim = flopy.mf6.MFSimulation( - sim_name=testgroup, sim_ws=ws, exe_name=exe_name_mf6 + sim_name=testgroup, sim_ws=ws, exe_name=exe ) tdis_rc = [(100.0, 10, 1.0), (100.0, 10, 1.0)] nper = len(tdis_rc) @@ -374,20 +349,7 @@ def run_flw_and_trnprt_models(): d0 = np.genfromtxt(fname, names=True, delimiter=",", deletechars="") print(d0.dtype.names) - return - - -def test_ssm06(): - run_flw_and_trnprt_models() - d = os.path.join(testdir, testgroup) - if os.path.isdir(d): - shutil.rmtree(d) - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - # run tests - test_ssm06() +def test_ssm06(function_tmpdir, targets): + mf6 = targets.mf6 + run_flw_and_trnprt_models(str(function_tmpdir), mf6) diff --git a/autotest/test_gwt_ssm06fmi.py b/autotest/test_gwt_ssm06fmi.py index 47db31182a9..71c243a3449 100644 --- a/autotest/test_gwt_ssm06fmi.py +++ b/autotest/test_gwt_ssm06fmi.py @@ -8,38 +8,11 @@ # separately never threw the error. import os -import shutil +import flopy import numpy as np -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - - -import targets - -exe_name_mf6 = targets.target_dict["mf6"] -exe_name_mf6 = os.path.abspath(exe_name_mf6) - -testdir = "./temp" testgroup = "ssm06fmi" -d = os.path.join(testdir, testgroup) -if os.path.isdir(d): - shutil.rmtree(d) - nlay = 1 nrow = 10 @@ -72,13 +45,13 @@ ndv = 0 -def run_flow_model(): +def run_flow_model(dir, exe): global idomain name = "flow" gwfname = name - wsf = os.path.join(testdir, testgroup, name) + wsf = os.path.join(dir, testgroup, name) sim = flopy.mf6.MFSimulation( - sim_name=name, sim_ws=wsf, exe_name=exe_name_mf6 + sim_name=name, sim_ws=wsf, exe_name=exe ) tdis_rc = [(100.0, 1, 1.0), (100.0, 1, 1.0)] nper = len(tdis_rc) @@ -269,17 +242,15 @@ def run_flow_model(): errmsg = f"flow model did not terminate successfully\n{buff}" assert success, errmsg - return - -def run_transport_model(): +def run_transport_model(dir, exe): name = "transport" gwtname = name - wst = os.path.join(testdir, testgroup, name) + wst = os.path.join(dir, testgroup, name) sim = flopy.mf6.MFSimulation( sim_name=name, version="mf6", - exe_name=exe_name_mf6, + exe_name=exe, sim_ws=wst, continue_=False, ) @@ -408,21 +379,9 @@ def run_transport_model(): fname = os.path.join(wst, fname) d0 = np.genfromtxt(fname, names=True, delimiter=",", deletechars="") print(d0.dtype.names) - return - - -def test_ssm06fmi(): - run_flow_model() - run_transport_model() - d = os.path.join(testdir, testgroup) - if os.path.isdir(d): - shutil.rmtree(d) - return - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - # run tests - test_ssm06fmi() +def test_ssm06fmi(function_tmpdir, targets): + mf6 = targets.mf6 + run_flow_model(str(function_tmpdir), mf6) + run_transport_model(str(function_tmpdir), mf6) diff --git a/autotest/test_gwt_uzt01.py b/autotest/test_gwt_uzt01.py index 01946fb5b5d..62d137adade 100644 --- a/autotest/test_gwt_uzt01.py +++ b/autotest/test_gwt_uzt01.py @@ -11,30 +11,11 @@ import numpy as np import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from framework import testing_framework -from simulation import Simulation +import flopy + +from harness import TestHarness, TestConfig ex = ["uzt01a"] -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) -ddir = "data" nlay, nrow, ncol = 15, 1, 1 @@ -403,8 +384,8 @@ def build_model(idx, dir): def make_plot(sim, obsvals): print("making plots...") - name = ex[sim.idxsim] - ws = exdirs[sim.idxsim] + name = sim.name + ws = sim.simpath # shows curves for times 2.5, 7.5, 12.6, 17.7 # which are indices 24, 74, 125, and -1 @@ -438,8 +419,8 @@ def make_plot(sim, obsvals): def check_obs(sim): print("checking obs...") - name = ex[sim.idxsim] - ws = exdirs[sim.idxsim] + name = sim.name + ws = sim.simpath sim = flopy.mf6.MFSimulation.load(sim_ws=ws) gwfname = "gwf_" + name gwtname = "gwt_" + name @@ -506,16 +487,15 @@ def check_obs(sim): ) assert success, "One or more UZT obs checks did not pass" - return def eval_flow(sim): print("evaluating flow...") - name = ex[sim.idxsim] + name = sim.name gwfname = "gwf_" + name gwtname = "gwt_" + name - ws = exdirs[sim.idxsim] + ws = sim.simpath # check binary grid file fname = os.path.join(ws, gwfname + ".dis.grb") @@ -581,47 +561,17 @@ def eval_flow(sim): # Make plot of obs fpth = os.path.join(sim.simpath, gwtname + ".uzt.obs.concentration.csv") - try: - obsvals = np.genfromtxt(fpth, names=True, delimiter=",") - except: - assert False, f'could not load data from "{fpth}"' - if False: - make_plot(sim, obsvals) - return + obsvals = np.genfromtxt(fpth, names=True, delimiter=",") + + # make_plot(sim, obsvals) -# - No need to change any code below @pytest.mark.parametrize( - "idx, dir", - list(enumerate(exdirs)), + "name", + ex, ) -def test_mf6model(idx, dir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, dir) - - # run the test model - test.run_mf6(Simulation(dir, exfunc=eval_flow, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test model - for idx, dir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, dir) - sim = Simulation(dir, exfunc=eval_flow, idxsim=idx) - test.run_mf6(sim) - - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, 0, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=eval_flow, idxsim=0), ws) diff --git a/autotest/test_gwtgwt_oldexg.py b/autotest/test_gwtgwt_oldexg.py index 21e91f109d6..9352334b5fd 100644 --- a/autotest/test_gwtgwt_oldexg.py +++ b/autotest/test_gwtgwt_oldexg.py @@ -3,16 +3,9 @@ import numpy as np import pytest -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) +import flopy -from framework import testing_framework -from simulation import Simulation +from harness import TestHarness, TestConfig # Test compatibility of GWT-GWT with the 'classic' GWF exchange. # It compares the result of a single reference model @@ -38,10 +31,6 @@ ex = ["gwtgwt_oldexg"] use_ifmod = False -exdirs = [] -for s in ex: - exdirs.append(os.path.join("temp", s)) - # some global convenience...: # model names mname_ref = "refmodel" @@ -719,8 +708,6 @@ def compare_gwf_to_ref(sim): errmsg = f"min or max residual too large {res.min()} {res.max()}" assert np.allclose(res, 0.0, atol=1.0e-6), errmsg - return - def compare_gwt_to_ref(sim): print("comparing concentration to single model reference...") @@ -781,41 +768,13 @@ def compare_gwt_to_ref(sim): errmsg = f"min or max residual too large {res.min()} {res.max()}" assert np.allclose(res, 0.0, atol=1.0e-6), errmsg - return - -# - No need to change any code below @pytest.mark.parametrize( - "idx, exdir", - list(enumerate(exdirs)), + "idx, name", + list(enumerate(ex)), ) -def test_mf6model(idx, exdir): - # initialize testing framework - test = testing_framework() - - # build the model - test.build_mf6_models(build_model, idx, exdir) - - # run the test model - test.run_mf6(Simulation(exdir, exfunc=compare_to_ref, idxsim=idx)) - - -def main(): - # initialize testing framework - test = testing_framework() - - # run the test models - for idx, exdir in enumerate(exdirs): - test.build_mf6_models(build_model, idx, exdir) - - sim = Simulation(exdir, exfunc=compare_to_ref, idxsim=idx) - test.run_mf6(sim) - return - - -if __name__ == "__main__": - # print message - print(f"standalone run of {os.path.basename(__file__)}") - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + test = TestHarness() + test.build(build_model, idx, ws) + test.run(TestConfig(name=name, exes=targets, exfunc=compare_to_ref, idxsim=idx), ws) diff --git a/autotest/test_largetestmodels.py b/autotest/test_largetestmodels.py new file mode 100644 index 00000000000..bca5d200489 --- /dev/null +++ b/autotest/test_largetestmodels.py @@ -0,0 +1,35 @@ +from pathlib import Path + +import pytest +from modflow_devtools.executables import Executables + +from harness import TestConfig +from conftest import should_compare + + +@pytest.mark.slow +@pytest.mark.repo +@pytest.mark.regression +def test_large_model( + function_tmpdir: Path, + large_test_model: Path, + targets: Executables, + original_regression: bool): + name = large_test_model.parent.name + comparisons = { + "test1004_mvlake_laksfr_tr": ("6.2.2",), + "test1004_mvlake_lak_tr": ("6.2.1",), + "test1003_MNW2_Fig28": ("6.2.1",), + "test1001_Peterson": ("6.2.1",), + } + test = TestConfig( + name=name, + exes=targets, + mf6_regression=not original_regression, + cmp_verbose=False, + make_comparison=should_compare(name, comparisons, targets), + ) + + test.setup(str(large_test_model.parent), str(function_tmpdir / name)) + test.run() + test.compare() diff --git a/autotest/test_mf6_tmp_simulations.py b/autotest/test_mf6_tmp_simulations.py index c97cea10dc8..92312aeb32c 100644 --- a/autotest/test_mf6_tmp_simulations.py +++ b/autotest/test_mf6_tmp_simulations.py @@ -3,23 +3,7 @@ import pytest -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from simulation import Simulation +from harness import TestConfig, get_namefiles, get_mf6_ftypes exdir = os.path.join("..", "tmp_simulations") testpaths = os.path.join("..", exdir) @@ -87,10 +71,10 @@ def get_mf6_models(): found_dirs = [] for d in dirs: pth = os.path.join(exdir, d) - namefiles = pymake.get_namefiles(pth) + namefiles = get_namefiles(pth) ftypes = [] for namefile in namefiles: - ftype = pymake.autotest.get_mf6_ftypes( + ftype = get_mf6_ftypes( namefile, select_packages ) if ftype not in ftypes: @@ -112,7 +96,7 @@ def get_mf6_models(): return dirs -def run_mf6(sim): +def run_mf6(sim, ws): """ Run the MODFLOW 6 simulation and compare to existing head file or appropriate MODFLOW-2005, MODFLOW-NWT, MODFLOW-USG, or MODFLOW-LGR run. @@ -120,49 +104,16 @@ def run_mf6(sim): """ print(os.getcwd()) src = os.path.join(exdir, sim.name) - dst = os.path.join("temp", sim.name) + dst = os.path.join(ws, sim.name) sim.setup(src, dst) sim.run() sim.compare() - sim.teardown() @pytest.mark.parametrize( - "idx, dir", + "idx, name", list(enumerate(get_mf6_models())), ) -def test_mf6model(idx, dir): - # run the test model - run_mf6(Simulation(dir)) - - -def main(): - # write message - tnam = os.path.splitext(os.path.basename(__file__))[0] - msg = f"Running {tnam} test" - print(msg) - - # get a list of test models to run - dirs = get_mf6_models() - - # run the test model - for dir in dirs: - sim = Simulation(dir) - run_mf6(sim) - - return - - -if __name__ == "__main__": - - print(f"standalone run of {os.path.basename(__file__)}") - - delFiles = True - for idx, arg in enumerate(sys.argv): - if arg.lower() == "--keep": - if len(sys.argv) > idx + 1: - delFiles = False - break - - # run main routine - main() +def test_mf6model(idx, name, function_tmpdir, targets): + ws = str(function_tmpdir) + run_mf6(TestConfig(name=name, exes=targets), ws) diff --git a/autotest/test_testmodels_mf5to6.py b/autotest/test_testmodels_mf5to6.py new file mode 100644 index 00000000000..ea20063b953 --- /dev/null +++ b/autotest/test_testmodels_mf5to6.py @@ -0,0 +1,89 @@ +import os +from pathlib import Path +from platform import system + +import flopy +import pytest +from modflow_devtools.executables import Executables + +from conftest import should_compare +from harness import TestConfig, model_setup, get_namefiles + + +@pytest.mark.slow +@pytest.mark.repo +@pytest.mark.regression +def test_model( + function_tmpdir: Path, + test_model_mf5to6: Path, + targets: Executables, + original_regression: bool): + # create test configuration + name = test_model_mf5to6.parent.name + + if test_model_mf5to6.parent.parent.name == "testWetDry" and name == "mf2005": + if system() == "Windows": + name = "testWetDry_mf2005" + else: + pytest.skip(f"Namefile {test_model_mf5to6} uses Windows path format") + + comparisons = { + "testPr2": ("6.2.1",), + "testUzfLakSfr": ("6.2.1",), + "testUzfLakSfr_laketable": ("6.2.1",), + "testWetDry": ("6.2.1",), + } + test = TestConfig( + name=name, + exes=targets, + mf6_regression=not original_regression, + cmp_verbose=False, + make_comparison=should_compare(name, comparisons, targets), + ) + + # set lgrpth to None + lgrpth = None + + # determine if compare directory exists in directory or if mflgr control + # file is in directory + src = str(test_model_mf5to6.parent) + listdir = os.listdir(src) + for value in listdir: + fpth = os.path.join(src, value) + if os.path.isfile(fpth): + ext = os.path.splitext(fpth)[1] + if ".lgr" in ext.lower(): + lgrpth = fpth + + print("Copying files to working directory") + # copy lgr files to working directory + if lgrpth is not None: + npth = lgrpth + model_setup(lgrpth, str(function_tmpdir)) + # copy MODFLOW-2005, MODFLOW-NWT, or MODFLOW-USG files to working directory + else: + npths = get_namefiles(src) + if len(npths) < 1: + msg = f"No name files in {src}" + print(msg) + assert False + npth = npths[0] + model_setup(npth, str(function_tmpdir)) + + # run the mf5to6 converter + mf5to6 = targets.mf5to6 + nam = os.path.basename(npth) + success, buff = flopy.run_model( + mf5to6, + nam, + model_ws=str(function_tmpdir), + silent=False, + report=True, + normal_msg="Program terminated normally", + cargs="mf6", + ) + assert success + + test.setup(str(function_tmpdir), os.path.join(function_tmpdir, test.name)) + test.run() + test.compare() diff --git a/autotest/test_testmodels_mf6.py b/autotest/test_testmodels_mf6.py new file mode 100644 index 00000000000..a1665cc448f --- /dev/null +++ b/autotest/test_testmodels_mf6.py @@ -0,0 +1,58 @@ +from pathlib import Path + +import pytest +from modflow_devtools.executables import Executables + +from conftest import should_compare +from harness import TestConfig + + +_excluded = [ + "alt_model", +] + + +@pytest.mark.slow +@pytest.mark.repo +@pytest.mark.regression +def test_model( + function_tmpdir: Path, + test_model_mf6: Path, + targets: Executables, + original_regression: bool): + name = test_model_mf6.parent.name + if name in _excluded: + pytest.skip(f"Example '{name}' is excluded") + + comparisons = { + "test001e_noUZF_3lay": ("6.2.1",), + "test005_advgw_tidal": ("6.2.1",), + "test017_Crinkle": ("6.2.1",), + "test028_sfr": ("6.2.1",), + "test028_sfr_rewet": ("6.2.1",), + "test028_sfr_rewet_nr": ("6.2.1",), + "test028_sfr_rewet_simple": ("6.2.1",), + "test028_sfr_simple": ("6.2.1",), + "test034_nwtp2": ("6.2.1",), + "test034_nwtp2_1d": ("6.2.1",), + "test045_lake1tr_nr": ("6.2.1",), + "test045_lake2tr": ("6.2.1",), + "test045_lake2tr_nr": ("6.2.1",), + "test051_uzfp2": ("6.2.1",), + "test051_uzfp3_lakmvr_v2": ("6.2.1",), + "test051_uzfp3_wellakmvr_v2": ("6.2.1",), + "test045_lake4ss": ("6.2.2",), + "test056_mt3dms_usgs_gwtex_dev": ("6.2.2",), + "test056_mt3dms_usgs_gwtex_IR_dev": ("6.2.2",), + } + test = TestConfig( + name=name, + exes=targets, + mf6_regression=not original_regression, + cmp_verbose=False, + make_comparison=should_compare(name, comparisons, targets), + ) + + test.setup(str(test_model_mf6.parent), str(function_tmpdir / name)) + test.run() + test.compare() diff --git a/autotest/test_z01_testmodels_mf6.py b/autotest/test_z01_testmodels_mf6.py deleted file mode 100644 index ad4f6fae38b..00000000000 --- a/autotest/test_z01_testmodels_mf6.py +++ /dev/null @@ -1,264 +0,0 @@ -import os -import subprocess -import sys - -import pytest - -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from common_regression import ( - get_example_basedir, - get_example_dirs, - get_home_dir, - get_select_dirs, - get_select_packages, - is_directory_available, - set_mf6_regression, -) -from simulation import Simulation -from targets import get_mf6_version - -# find path to examples directory -home = get_home_dir() - -find_dir = "modflow6-testmodels" -example_basedir = get_example_basedir(home, find_dir, subdir="mf6") - -if example_basedir is not None: - assert os.path.isdir(example_basedir) - - -def get_branch(): - try: - # determine current buildstat branch - b = subprocess.Popen( - ("git", "status"), stdout=subprocess.PIPE, stderr=subprocess.STDOUT - ).communicate()[0] - if isinstance(b, bytes): - b = b.decode("utf-8") - - # determine current buildstat branch - for line in b.splitlines(): - if "On branch" in line: - branch = line.replace("On branch ", "").rstrip() - except: - branch = None - - return branch - - -def get_mf6_models(): - """ - Get a list of test models - """ - - # determine if test directory exists - dir_avail = is_directory_available(example_basedir) - if not dir_avail: - return [] - - # determine if running on travis - is_CI = "CI" in os.environ - - # get current branch - if is_CI: - branch = os.path.basename(os.environ["GITHUB_REF"]) - else: - branch = get_branch() - print(f"On branch {branch}") - - # tuple of example files to exclude - # exclude = (None,) - exclude = ("test205_gwtbuy-henrytidal",) - - # update exclude - if is_CI: - exclude_CI = (None,) - exclude = exclude + exclude_CI - exclude = list(exclude) - - # write a summary of the files to exclude - print("list of tests to exclude:") - for idx, ex in enumerate(exclude): - print(f" {idx + 1}: {ex}") - - # build list of directories with valid example files - if example_basedir is not None: - example_dirs = get_example_dirs( - example_basedir, exclude, prefix="test" - ) - else: - example_dirs = [] - - # exclude dev examples on master or release branches - if "master" in branch.lower() or "release" in branch.lower() or branch.lower().startswith("v6"): - drmv = [] - for d in example_dirs: - if "_dev" in d.lower(): - drmv.append(d) - for d in drmv: - example_dirs.remove(d) - - # determine if only a selection of models should be run - select_example_dirs = None - select_packages = None - for idx, arg in enumerate(sys.argv): - if arg.lower() == "--sim": - if len(sys.argv) > idx + 1: - select_example_dirs = sys.argv[idx + 1 :] - break - elif arg.lower() == "--pak": - if len(sys.argv) > idx + 1: - select_packages = sys.argv[idx + 1 :] - select_packages = [item.upper() for item in select_packages] - break - elif arg.lower() == "--match": - if len(sys.argv) > idx + 1: - like = sys.argv[idx + 1] - example_dirs = [item for item in example_dirs if like in item] - break - - # determine if the selection of model is in the test models to evaluate - if select_example_dirs is not None: - example_dirs = get_select_dirs(select_example_dirs, example_dirs) - if len(example_dirs) < 1: - msg = "Selected models not available in test" - print(msg) - - # determine if the specified package(s) is in the test models to evaluate - if select_packages is not None: - example_dirs = get_select_packages( - select_packages, example_basedir, example_dirs - ) - if len(example_dirs) < 1: - msg = "Selected packages not available [" - for pak in select_packages: - msg += f" {pak}" - msg += "]" - print(msg) - - return example_dirs - - -def run_mf6(sim): - """ - Run the MODFLOW 6 simulation and compare to results generated using - 1) the current MODFLOW 6 release, 2) an existing head file, or 3) or - appropriate MODFLOW-2005, MODFLOW-NWT, MODFLOW-USG, or MODFLOW-LGR run. - - """ - print("Current working directory: ".format(os.getcwd())) - src = os.path.join(example_basedir, sim.name) - dst = os.path.join("temp", sim.name) - sim.setup(src, dst) - sim.run() - sim.compare() - sim.teardown() - - -def set_make_comparison(test): - compare_tests = { - "test001e_noUZF_3lay": ("6.2.1",), - "test005_advgw_tidal": ("6.2.1",), - "test017_Crinkle": ("6.2.1",), - "test028_sfr": ("6.2.1",), - "test028_sfr_rewet": ("6.2.1",), - "test028_sfr_rewet_nr": ("6.2.1",), - "test028_sfr_rewet_simple": ("6.2.1",), - "test028_sfr_simple": ("6.2.1",), - "test034_nwtp2": ("6.2.1",), - "test034_nwtp2_1d": ("6.2.1",), - "test045_lake1tr_nr": ("6.2.1",), - "test045_lake2tr": ("6.2.1",), - "test045_lake2tr_nr": ("6.2.1",), - "test051_uzfp2": ("6.2.1",), - "test051_uzfp3_lakmvr_v2": ("6.2.1",), - "test051_uzfp3_wellakmvr_v2": ("6.2.1",), - "test045_lake4ss": ("6.2.2",), - "test056_mt3dms_usgs_gwtex_dev": ("6.2.2",), - "test056_mt3dms_usgs_gwtex_IR_dev": ("6.2.2",), - } - make_comparison = True - if test in compare_tests.keys(): - version = get_mf6_version() - print(f"MODFLOW version='{version}'") - version = get_mf6_version(version="mf6-regression") - print(f"MODFLOW regression version='{version}'") - if version in compare_tests[test]: - make_comparison = False - return make_comparison - - -mf6_models = get_mf6_models() - - -@pytest.mark.parametrize( - "exdir", - mf6_models, -) -def test_mf6model(exdir): - # run the test model - run_mf6( - Simulation( - exdir, - mf6_regression=set_mf6_regression(), - cmp_verbose=False, - make_comparison=set_make_comparison(exdir), - ) - ) - - -def main(): - # write message - tnam = os.path.splitext(os.path.basename(__file__))[0] - msg = f"Running {tnam} test" - print(msg) - - # determine if test directory exists - dir_available = is_directory_available(example_basedir) - if not dir_available: - return - - # get a list of test models to run - example_dirs = get_mf6_models() - - # run the test model - for on_dir in example_dirs: - sim = Simulation( - on_dir, - mf6_regression=set_mf6_regression(), - cmp_verbose=True, - make_comparison=set_make_comparison(on_dir), - ) - run_mf6(sim) - - return - - -if __name__ == "__main__": - - print(f"standalone run of {os.path.basename(__file__)}") - - delFiles = True - for idx, arg in enumerate(sys.argv): - if arg.lower() == "--keep": - if len(sys.argv) > idx + 1: - delFiles = False - break - - # run main routine - main() diff --git a/autotest/test_z02_testmodels_mf5to6.py b/autotest/test_z02_testmodels_mf5to6.py deleted file mode 100644 index cd11f613889..00000000000 --- a/autotest/test_z02_testmodels_mf5to6.py +++ /dev/null @@ -1,277 +0,0 @@ -import os -import pathlib -import shutil -import sys -import time - -import pytest - -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from common_regression import ( - get_example_basedir, - get_example_dirs, - get_home_dir, - get_select_dirs, - get_select_packages, - is_directory_available, - set_mf6_regression, -) -from simulation import Simulation -from targets import get_mf6_version -from targets import target_dict as target_dict - -# find path to examples directory -home = get_home_dir() - - -def get_mf5to6_models(): - """ - Get a list of test models - """ - - # determine if test directory exists - dir_available = is_directory_available(example_basedir) - if not dir_available: - return [] - - # list of example files to exclude - exclude = (None,) - - # write a summary of the files to exclude - print("list of tests to exclude:") - for idx, ex in enumerate(exclude): - print(f" {idx + 1}: {ex}") - - # build list of directories with valid example files - if example_basedir is not None: - example_dirs = get_example_dirs( - example_basedir, - exclude, - prefix="test", - find_sim=False, - ) - else: - example_dirs = [] - - # determine if only a selection of models should be run - select_dirs = None - select_packages = None - for idx, arg in enumerate(sys.argv): - if arg.lower() == "--sim": - if len(sys.argv) > idx + 1: - select_dirs = sys.argv[idx + 1 :] - break - elif arg.lower() == "--pak": - if len(sys.argv) > idx + 1: - select_packages = sys.argv[idx + 1 :] - select_packages = [item.upper() for item in select_packages] - break - - # determine if the selection of model is in the test models to evaluate - if select_dirs is not None: - example_dirs = get_select_dirs(select_dirs, example_dirs) - if len(example_dirs) < 1: - msg = "Selected models not available in test" - print(msg) - - # determine if the specified package(s) is in the test models to evaluate - if select_packages is not None: - example_dirs = get_select_packages( - select_packages, example_basedir, example_dirs - ) - if len(example_dirs) < 1: - msg = "Selected packages not available [" - for idx, pak in enumerate(select_packages): - msg += f"{pak}" - if idx + 1 < len(select_packages): - msg += ", " - msg += "]" - print(msg) - - return example_dirs - - -find_dir = "modflow6-testmodels" -example_basedir = get_example_basedir(home, find_dir, subdir="mf5to6") - -if example_basedir is not None: - assert os.path.isdir(example_basedir) - -# get a list of test models to run -mf5to6_models = get_mf5to6_models() - - -sfmt = "{:25s} - {}" - - -def run_mf5to6(sim): - """ - Run the MODFLOW 6 simulation and compare to existing head file or - appropriate MODFLOW-2005, MODFLOW-NWT, MODFLOW-USG, or MODFLOW-LGR run. - - """ - src = os.path.join(example_basedir, sim.name) - dst = os.path.join("temp", f"z02_mf5to6_{sim.name}") - os.makedirs(dst, exist_ok=True) - - # set lgrpth to None - lgrpth = None - - # determine if compare directory exists in directory or if mflgr control - # file is in directory - listdir = os.listdir(src) - for value in listdir: - fpth = os.path.join(src, value) - if os.path.isfile(fpth): - ext = os.path.splitext(fpth)[1] - if ".lgr" in ext.lower(): - lgrpth = fpth - - print("Copying files to working directory") - # copy lgr files to working directory - if lgrpth is not None: - npth = lgrpth - pymake.setup(lgrpth, dst) - # copy MODFLOW-2005, MODFLOW-NWT, or MODFLOW-USG files to working directory - else: - npths = pymake.get_namefiles(src) - if len(npths) < 1: - msg = f"No name files in {src}" - print(msg) - assert False - npth = npths[0] - pymake.setup(npth, dst) - - # run the mf5to6 converter - exe = os.path.abspath(target_dict["mf5to6"]) - print(sfmt.format("using executable", exe)) - nmsg = "Program terminated normally" - try: - nam = os.path.basename(npth) - success, buff = flopy.run_model( - exe, - nam, - model_ws=dst, - silent=False, - report=True, - normal_msg=nmsg, - cargs="mf6", - ) - msg = sfmt.format("MODFLOW 5 to 6 run", nam) - if success: - print(msg) - else: - print("ERROR: " + msg) - except: - msg = sfmt.format("MODFLOW 5 to 6 run", nam) - print("ERROR: " + msg) - success = False - - assert success, msg - - # standard setup - src = dst - dst = os.path.join("temp", f"z02_mf6_{sim.name}") - sim.setup(src, dst) - - # clean up temp/working directory (src) - if os.path.exists(src): - msg = f"Removing {src} directory" - print(msg) - shutil.rmtree(src) - time.sleep(0.5) - - # standard comparison run - sim.run() - sim.compare() - sim.teardown() - - -def set_make_comparison(test): - compare_tests = { - "testPr2": ("6.2.1",), - "testUzfLakSfr": ("6.2.1",), - "testUzfLakSfr_laketable": ("6.2.1",), - "testWetDry": ("6.2.1",), - } - make_comparison = True - if test in compare_tests.keys(): - version = get_mf6_version() - print(f"MODFLOW version='{version}'") - version = get_mf6_version(version="mf6-regression") - print(f"MODFLOW regression version='{version}'") - if version in compare_tests[test]: - make_comparison = False - return make_comparison - - -@pytest.mark.parametrize( - "exdir", - mf5to6_models, -) -def test_model(exdir): - run_mf5to6( - Simulation( - exdir, - mf6_regression=set_mf6_regression(), - cmp_verbose=False, - make_comparison=set_make_comparison(exdir), - ) - ) - - return - - -def main(): - # write message - tnam = os.path.splitext(os.path.basename(__file__))[0] - msg = f"Running {tnam} test" - print(msg) - - # get name of current file - module_name = sys.modules[__name__].__file__ - - # # get a list of test models to run - # example_dirs = get_mf5to6_models() - - # run the test model - for on_dir in mf5to6_models: - sim = Simulation( - on_dir, - mf6_regression=set_mf6_regression(), - cmp_verbose=False, - make_comparison=set_make_comparison(on_dir), - ) - run_mf5to6(sim) - - return - - -if __name__ == "__main__": - - print(f"standalone run of {os.path.basename(__file__)}") - - delFiles = True - for idx, arg in enumerate(sys.argv): - if arg.lower() == "--keep": - if len(sys.argv) > idx + 1: - delFiles = False - break - - # run main routine - main() diff --git a/autotest/test_z03_examples.py b/autotest/test_z03_examples.py deleted file mode 100644 index 6983e411a9b..00000000000 --- a/autotest/test_z03_examples.py +++ /dev/null @@ -1,214 +0,0 @@ -import os -import sys - -import pytest - -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from common_regression import ( - get_example_basedir, - get_example_dirs, - get_home_dir, - get_select_dirs, - get_select_packages, - is_directory_available, -) -from simulation import Simulation -from targets import get_mf6_version - -# find path to modflow6-examples directory -home = get_home_dir() - -# get example_basedir -find_dir = "modflow6-examples" -example_basedir = get_example_basedir(home, find_dir, subdir="examples") - - -def get_mf6_models(): - """ - Get a list of test models - """ - - # determine if examples directory exists - dir_available = is_directory_available(example_basedir) - if not dir_available: - return [] - - # determine if running on travis - is_CI = "CI" in os.environ - - # tuple of example files to exclude - exclude = ("ex-gwf-csub-p02c",) - - # update exclude - if is_CI: - exclude_CI = (None,) - exclude = exclude + exclude_CI - exclude = list(exclude) - - # write a summary of the files to exclude - print("list of tests to exclude:") - for idx, ex in enumerate(exclude): - print(f" {idx + 1}: {ex}") - - # build list of directories with valid example files - if example_basedir is not None: - example_dirs = get_example_dirs(example_basedir, exclude, prefix="ex-") - else: - example_dirs = [] - - # determine if only a selection of models should be run - select_dirs = None - select_packages = None - for idx, arg in enumerate(sys.argv): - if arg.lower() == "--sim": - if len(sys.argv) > idx + 1: - select_dirs = sys.argv[idx + 1 :] - break - elif arg.lower() == "--pak": - if len(sys.argv) > idx + 1: - select_packages = sys.argv[idx + 1 :] - select_packages = [item.upper() for item in select_packages] - break - - # determine if the selection of model is in the test models to evaluate - if select_dirs is not None: - example_dirs = get_select_dirs(select_dirs, example_dirs) - if len(example_dirs) < 1: - msg = "Selected models not available in test" - print(msg) - - # determine if the specified package(s) is in the test models to evaluate - if select_packages is not None: - example_dirs = get_select_packages( - select_packages, example_basedir, example_dirs - ) - if len(example_dirs) < 1: - msg = "Selected packages not available [" - for pak in select_packages: - msg += f" {pak}" - msg += "]" - print(msg) - - return example_dirs - - -def run_mf6(sim): - """ - Run the MODFLOW 6 simulation and compare to existing head file or - appropriate MODFLOW-2005, MODFLOW-NWT, MODFLOW-USG, or MODFLOW-LGR run. - - """ - print(os.getcwd()) - src = os.path.join(example_basedir, sim.name) - dst = os.path.join("temp", sim.name) - sim.setup(src, dst) - sim.run() - sim.compare() - sim.teardown() - - -def set_make_comparison(test): - compare_tests = { - "ex-gwf-capture": ("6.2.1",), - "ex-gwf-sagehen": ("6.2.1",), - "ex-gwf-sfr-p01b": ("6.2.1",), - "ex-gwf-nwt-p02a": ("6.2.1",), - "ex-gwf-lak-p01": ("6.2.1",), - "ex-gwf-lak-p02": ("6.2.1",), - "ex-gwf-nwt-p02b": ("6.2.1",), - "ex-gwf-advtidal": ("6.2.1",), - "ex-gwf-sfr-p01": ("6.2.1",), - "ex-gwf-lgr": ("6.2.2",), - "ex-gwt-rotate": ("6.2.2",), - "ex-gwt-gwtgwt-mt3dms-p10": ("6.3.0",), - } - make_comparison = True - if test in compare_tests.keys(): - version = get_mf6_version() - print(f"MODFLOW version='{version}'") - version = get_mf6_version(version="mf6-regression") - print(f"MODFLOW regression version='{version}'") - if version in compare_tests[test]: - print( - f"Test {test} does not run with versions {compare_tests[test]}" - ) - print( - f"Skipping regression test of sim {test} because the version is {version}" - ) - make_comparison = False - return make_comparison - - -mf6_models = get_mf6_models() - - -@pytest.mark.parametrize( - "exdir", - mf6_models, -) -def test_mf6model(exdir): - # run the test model - run_mf6( - Simulation( - exdir, - mf6_regression=True, - cmp_verbose=False, - make_comparison=set_make_comparison(exdir), - ) - ) - - -def main(): - # write message - tnam = os.path.splitext(os.path.basename(__file__))[0] - msg = f"Running {tnam} test" - print(msg) - - # get a list of test models to run - example_dirs = get_mf6_models() - - # run the test model - for on_dir in example_dirs: - mf6_regression = True - make_comparison = set_make_comparison(on_dir) - if not make_comparison: - mf6_regression = False - sim = Simulation( - on_dir, - mf6_regression=mf6_regression, - cmp_verbose=False, - make_comparison=make_comparison, - ) - run_mf6(sim) - - return - - -if __name__ == "__main__": - - print(f"standalone run of {os.path.basename(__file__)}") - - delFiles = True - for idx, arg in enumerate(sys.argv): - if arg.lower() == "--keep": - if len(sys.argv) > idx + 1: - delFiles = False - break - - # run main routine - main() diff --git a/autotest/test_z03_largetestmodels.py b/autotest/test_z03_largetestmodels.py deleted file mode 100644 index dc3fa8e2c8f..00000000000 --- a/autotest/test_z03_largetestmodels.py +++ /dev/null @@ -1,197 +0,0 @@ -import os -import sys - -import pytest - -try: - import pymake -except: - msg = "Error. Pymake package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install https://github.com/modflowpy/pymake/zipball/master" - raise Exception(msg) - -try: - import flopy -except: - msg = "Error. FloPy package is not available.\n" - msg += "Try installing using the following command:\n" - msg += " pip install flopy" - raise Exception(msg) - -from common_regression import ( - get_example_basedir, - get_example_dirs, - get_home_dir, - get_select_dirs, - get_select_packages, - is_directory_available, - set_mf6_regression, -) -from simulation import Simulation -from targets import get_mf6_version - -home = get_home_dir() - -find_dir = "modflow6-largetestmodels" -example_basedir = get_example_basedir(home, find_dir) - - -def get_mf6_models(): - """ - Get a list of test models - """ - - # determine if largetest directory exists - dir_available = is_directory_available(example_basedir) - if not dir_available: - return [] - - # determine if running on CI - is_CI = "CI" in os.environ - - # tuple of example files to exclude - exclude = (None,) - - # update exclude - if is_CI: - exclude_CI = (None,) - exclude = exclude + exclude_CI - exclude = list(exclude) - - # write a summary of the files to exclude - print("list of tests to exclude:") - for idx, ex in enumerate(exclude): - print(f" {idx + 1}: {ex}") - - # build list of directories with valid example files - if example_basedir is not None: - example_dirs = get_example_dirs( - example_basedir, exclude, prefix="test" - ) - else: - example_dirs = [] - - # determine if only a selection of models should be run - select_dirs = None - select_packages = None - for idx, arg in enumerate(sys.argv): - if arg.lower() == "--sim": - if len(sys.argv) > idx + 1: - select_dirs = sys.argv[idx + 1 :] - break - elif arg.lower() == "--pak": - if len(sys.argv) > idx + 1: - select_packages = sys.argv[idx + 1 :] - select_packages = [item.upper() for item in select_packages] - break - - # determine if the selection of model is in the test models to evaluate - if select_dirs is not None: - example_dirs = get_select_dirs(select_dirs, example_dirs) - if len(example_dirs) < 1: - msg = "Selected models not available in test" - print(msg) - - # determine if the specified package(s) is in the test models to evaluate - if select_packages is not None: - example_dirs = get_select_packages( - select_packages, example_basedir, example_dirs - ) - if len(example_dirs) < 1: - msg = "Selected packages not available [" - for pak in select_packages: - msg += f" {pak}" - msg += "]" - print(msg) - - return example_dirs - - -def run_mf6(sim): - """ - Run the MODFLOW 6 simulation and compare to existing head file or - appropriate MODFLOW-2005, MODFLOW-NWT, MODFLOW-USG, or MODFLOW-LGR run. - - """ - print(os.getcwd()) - src = os.path.join(example_basedir, sim.name) - dst = os.path.join("temp", sim.name) - sim.setup(src, dst) - sim.run() - sim.compare() - sim.teardown() - - -def set_make_comparison(test): - compare_tests = { - "test1004_mvlake_laksfr_tr": ("6.2.2",), - "test1004_mvlake_lak_tr": ("6.2.1",), - "test1003_MNW2_Fig28": ("6.2.1",), - "test1001_Peterson": ("6.2.1",), - } - make_comparison = True - if test in compare_tests.keys(): - version = get_mf6_version() - print(f"MODFLOW version='{version}'") - version = get_mf6_version(version="mf6-regression") - print(f"MODFLOW regression version='{version}'") - if version in compare_tests[test]: - make_comparison = False - return make_comparison - - -mf6_models = get_mf6_models() - - -@pytest.mark.parametrize( - "exdir", - mf6_models, -) -def test_mf6model(exdir): - # run the test model - run_mf6( - Simulation( - exdir, - mf6_regression=set_mf6_regression(), - cmp_verbose=False, - make_comparison=set_make_comparison(exdir), - ) - ) - - -def main(): - # write message - tnam = os.path.splitext(os.path.basename(__file__))[0] - msg = f"Running {tnam} test" - print(msg) - - # get a list of test models to run - example_dirs = get_mf6_models() - - # run the test model - for on_dir in example_dirs: - sim = Simulation( - on_dir, - mf6_regression=set_mf6_regression(), - cmp_verbose=False, - make_comparison=set_make_comparison(on_dir), - ) - run_mf6(sim) - - return - - -if __name__ == "__main__": - - print(f"standalone run of {os.path.basename(__file__)}") - - delFiles = True - for idx, arg in enumerate(sys.argv): - if arg.lower() == "--keep": - if len(sys.argv) > idx + 1: - delFiles = False - break - - # run main routine - main() diff --git a/autotest/update_flopy.py b/autotest/update_flopy.py index 42db0b3539e..e079b389f34 100644 --- a/autotest/update_flopy.py +++ b/autotest/update_flopy.py @@ -1,26 +1,18 @@ +import argparse import importlib import os import shutil import subprocess -from contextlib import contextmanager +from pathlib import Path import flopy + flopypth = flopy.__path__[0] print(f"flopy is installed in {flopypth}") -@contextmanager -def cwd(path): - oldpwd = os.getcwd() - os.chdir(path) - try: - yield - finally: - os.chdir(oldpwd) - - -def test_delete_mf6(): +def delete_mf6(): pth = os.path.join(flopypth, "mf6", "modflow") files = [ entry @@ -30,7 +22,7 @@ def test_delete_mf6(): delete_files(files, pth, exclude="mfsimulation.py") -def test_delete_dfn(): +def delete_dfn(): pth = os.path.join(flopypth, "mf6", "data", "dfn") files = [ entry @@ -40,24 +32,23 @@ def test_delete_dfn(): delete_files(files, pth, exclude="flopy.dfn") -def test_copy_dfn(): - pth0 = os.path.join("..", "doc", "mf6io", "mf6ivar", "dfn") +def copy_dfn(path): files = [ entry - for entry in os.listdir(pth0) - if os.path.isfile(os.path.join(pth0, entry)) + for entry in os.listdir(path) + if os.path.isfile(os.path.join(path, entry)) ] pth1 = os.path.join(flopypth, "mf6", "data", "dfn") for fn in files: ext = os.path.splitext(fn)[1].lower() if "dfn" in ext: - fpth0 = os.path.join(pth0, fn) + fpth0 = os.path.join(path, fn) fpth1 = os.path.join(pth1, fn) - print(f'copying {fn} from "{pth0}" to "{pth1}"') + print(f'copying {fn} from "{path}" to "{pth1}"') shutil.copyfile(fpth0, fpth1) -def test_create_packages(): +def create_packages(): # get list of files in mf6/modflow pth = os.path.join(flopypth, "mf6", "modflow") list_files(pth) @@ -71,12 +62,9 @@ def test_create_packages(): exist = os.path.isfile(fpth) assert exist, f'"{fpth}" does not exist' - # run createrpackages.py script + # run createpackages.py script print(f"running...{fn}") - cmd = ["python", fn] - buff, ierr = run_command(cmd, pth) - assert ierr == 0, f"could not run {fn}" - print(f"successfully ran...{fn}") + subprocess.check_output(["python", "createpackages.py"], cwd=pth) # reload flopy print("reloading flopy") @@ -100,7 +88,6 @@ def list_files(pth, exts=["py"]): if ext in exts: idx += 1 print(f" {idx:5d} - {fn}") - return def delete_files(files, pth, allow_failure=False, exclude=None): @@ -124,47 +111,15 @@ def delete_files(files, pth, allow_failure=False, exclude=None): return True -def run_command(argv, pth, timeout=10): - with subprocess.Popen( - argv, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=pth - ) as process: - try: - output, unused_err = process.communicate(timeout=timeout) - buff = output.decode("utf-8") - ierr = process.returncode - except subprocess.TimeoutExpired: - process.kill() - output, unused_err = process.communicate() - buff = output.decode("utf-8") - ierr = 100 - except: - output, unused_err = process.communicate() - buff = output.decode("utf-8") - ierr = 101 - - return buff, ierr - - -def main(): - # write message - tnam = os.path.splitext(os.path.basename(__file__))[0] - msg = f"Running {tnam} test" - print(msg) - - print("deleting existing MODFLOW 6 FloPy files") - test_delete_mf6() - print("deleting existing MODFLOW 6 dfn files") - test_delete_dfn() - print("copying MODFLOW 6 repo dfn files") - test_copy_dfn() - print("creating MODFLOW 6 packages from repo dfn files") - test_create_packages() - - return - - if __name__ == "__main__": - print(f"standalone run of {os.path.basename(__file__)}") + parser = argparse.ArgumentParser("Update flopy from DFN files") + parser.add_argument("-p", "--path", help="path to DFN files") + args = parser.parse_args() + + path = Path(args.path).resolve() if args.path else Path(__file__).parent.parent / "doc" / "mf6io" / "mf6ivar" / "dfn" + print(f"Updating flopy packages from DFN files in: {path}") - # run main routine - main() + delete_mf6() + delete_dfn() + copy_dfn(path) + create_packages() diff --git a/distribution/benchmark.py b/distribution/benchmark.py index 547de7a3c66..5fddebb81d7 100644 --- a/distribution/benchmark.py +++ b/distribution/benchmark.py @@ -12,8 +12,8 @@ import flopy import pymake import pytest +from modflow_devtools.misc import get_model_dir_paths from modflow_devtools.build import meson_build -from modflow_devtools.misc import get_model_paths from utils import get_project_root_path @@ -322,7 +322,7 @@ def run_benchmarks( examples_path = Path(examples_path).expanduser().absolute() output_path = Path(output_path).expanduser().absolute() - example_dirs = get_model_paths(examples_path, excluded=excluded) + example_dirs = get_model_dir_paths(examples_path, excluded=excluded) assert any(example_dirs), f"No example model paths found, have models been built?" # results_path = output_path / _markdown_file_name diff --git a/distribution/build_dist.py b/distribution/build_dist.py index 87307667e1f..fc4a434cc28 100644 --- a/distribution/build_dist.py +++ b/distribution/build_dist.py @@ -13,7 +13,7 @@ from modflow_devtools.build import meson_build from modflow_devtools.download import download_and_unzip, get_release from modflow_devtools.markers import requires_exe -from modflow_devtools.misc import get_model_paths +from modflow_devtools.misc import get_model_dir_paths from build_docs import build_documentation from build_makefiles import build_mf6_makefile, build_mf5to6_makefile, build_zbud6_makefile @@ -147,7 +147,7 @@ def build_examples(examples_repo_path: PathLike, overwrite: bool = False): # create examples, but don't run them examples_path = examples_repo_path / "examples" examples_path.mkdir(parents=True, exist_ok=True) - if not overwrite and any(get_model_paths(examples_path)): + if not overwrite and any(get_model_dir_paths(examples_path)): print(f"Examples already built") else: print(f"Building examples") @@ -184,7 +184,7 @@ def setup_examples(bin_path: PathLike, examples_path: PathLike, overwrite: bool # list folders with mfsim.nam (recursively) # and add run.sh/bat script to each folder - model_paths = get_model_paths(examples_path) + model_paths = get_model_dir_paths(examples_path) for mp in model_paths: script_path = mp / f"run{_scext}" if not overwrite and script_path.is_file(): diff --git a/distribution/build_docs.py b/distribution/build_docs.py index 2a6b096e45d..752a621903c 100644 --- a/distribution/build_docs.py +++ b/distribution/build_docs.py @@ -472,7 +472,7 @@ def build_documentation(bin_path: PathLike, @requires_exe("pdflatex") -@pytest.mark.skip(reason="manual testing") +@pytest.mark.skip(reason="for manual testing") @pytest.mark.skipif(not (_benchmarks_path / "run-time-comparison.md").is_file(), reason="needs benchmarks") def test_build_documentation(tmp_path): bin_path = tmp_path / "bin"