FloPy Documentation

repository·develop·Indexed 17 days ago

https://github.com/modflowpy/flopy

FloPy is a Python library used to create, run, and post-process MODFLOW-based groundwater models. It supports various MODFLOW engines including MODFLOW 6, MODFLOW-2005, MODFLOW-NWT, MODFLOW-USG, and MODFLOW-2000, as well as transport and particle tracking models such as MODPATH (versions 6 and 7), MT3DMS, MT3D-USGS, and SEAWAT.

Tokens
19K
Snippets
59
Records
76
Agent score
70%

What's inside FloPy

  1. Supported MODFLOW models in FloPy

    develop

    FloPy provides support for a wide range of MODFLOW-based models, including:

    • MODFLOW engines: MODFLOW 6, MODFLOW-2005, MODFLOW-NWT, MODFLOW-USG, and MODFLOW-2000.
    • Transport and Particle Tracking: MODPATH (versions 6 and 7), MT3DMS, MT3D-USGS, and SEAWAT.
  2. Supported MODFLOW and related models in FloPy

    develop

    FloPy provides support for a wide range of MODFLOW-based models, including:

    • MODFLOW versions: MODFLOW 6, MODFLOW-2005, MODFLOW-NWT, MODFLOW-USG, and MODFLOW-2000.
    • Particle tracking: MODPATH (versions 6 and 7).
    • Transport models: MT3DMS, MT3D-USGS, and SEAWAT.
  3. Understand the MFStructure input specification hierarchy

    develop

    The flopy.mf6.data.mfstructure.MFStructure class is a singleton that represents the entire MODFLOW 6 input specification. It stores meta-data for all package files in a structured hierarchy, which FloPy uses to read/write files, create interfaces, and validate data constraints.

    The hierarchy follows this composition pattern:

    1. MFSimulationStructure: The top-level singleton. Contains MFModelStructure and MFInputFileStructure (for simulation-level packages like tdis, ims).
    2. MFModelStructure: Contains model-specific meta-data and an MFInputFileStructure for each package in that model.
    3. MFInputFileStructure: Contains package-specific meta-data and an MFBlockStructure for each block in the package.
    4. MFBlockStructure: Contains block-specific meta-data and an MFDataStructure for each data structure in the block.
    5. MFDataStructure: Defines the structure of grouped data (e.g., a numpy recarray).
    6. MFDataItemStructure: Defines the structure of specific data items (e.g., a single column in a recarray).
  4. Synchronize FloPy with MODFLOW 6 via DFN files

    develop
    FloPy must stay synchronized with the version of MODFLOW 6 being used. This is achieved using Definition (DFN) files that define the input/output formats. FloPy uses the generate_classes function in flopy.mf6.utils to automatically generate Python source code from these DFN files.
  5. Understand the relationship between MFPackage and MFData classes

    develop

    In the flopy.mf6 module, package and data classes are organized to map the physical structure of MODFLOW 6 files to Python objects:

    • MFPackage: The base class for all packages. It contains an MFInputFileStructure (defining file structure) and a dictionary of MFBlock objects.
    • MFBlock: Represents a block within a package. It contains an MFBlockStructure and a dictionary of MFData objects (subclasses of MFData), along with a list of MFBlockHeader objects (containing block names and optional items like iprn).
    • MFData: The abstract base class for data objects. All MFData subclasses contain an MFDataStructure defining their expected types and structure.

    Data Types

    There are three primary data types derived from MFData:

    1. MFList: Data stored in spreadsheets with different column headings (e.g., flow barrier descriptions). These are stored as numpy recarrays.
    2. MFArray: Data of a single type (e.g., integer values like HK values). These are stored as numpy ndarrays.
    3. MFScalar: Single data items, typically options.

    Transient Data

    Data defined for each stress period (e.g., period blocks) uses transient subclasses of the types above:

    • MFTransientList (subclass of MFList)
    • MFTransientArray (subclass of MFArray)
    • MFTransientScalar (subclass of MFScalar)
    • All transient types inherit from MFTransientData.
  6. Use snapshot testing for regression

    develop

    Snapshot testing verifies computations against previously captured "snapshots" using the syrupy library and fixtures from modflow-devtools.

    By default, tests run in comparison mode, meaning a new test will fail until a snapshot is created. To create or update snapshots, run pytest with the --snapshot-update flag.

  7. Perform benchmarking and profiling

    develop

    Performance testing is handled via pytest-benchmark.

    Benchmarking: Wrap a function call using the benchmark fixture. You can pass the function directly, pass arguments, or use a lambda for complex calls.

    def test_benchmark(benchmark):
        def sleep_s(s):
            import time
            time.sleep(s)
            return True
        assert benchmark(lambda: sleep_s(1))

    Profiling: To evaluate the call stack in detail, run tests with the --benchmark-cprofile flag. You can specify the sorting column (e.g., --benchmark-cprofile="tottime").

    Notes:

    • Benchmarking is automatically disabled when running tests in parallel (pytest-xdist).
    • Use --benchmark-disable to turn it off manually.
    • Use --benchmark-autosave to save results to a .benchmarks folder in the current working directory.
  8. Run FloPy tests

    develop

    Tests must be executed from the autotest directory.

    Basic Commands:

    • Run a specific test file in verbose mode: pytest -v <filename>.py
    • Run tests matching a specific pattern: pytest -v -k "<pattern>"
    • Run all tests in parallel using all available CPU cores: pytest -v -n auto (or specify a number like -n 2 or -n=2)

    Selecting tests with markers: Use the -m flag to filter tests by the following markers defined in pytest.ini:

    • slow: Tests that take longer than a few seconds.
    • example: Scripts, tutorials, and notebooks.
    • regression: Tests that compare multiple results.

    Smoke Testing: To run a fast subset of tests (excluding slow, example, and regression tests) that completes in under a minute, use the --smoke (or -S) alias:

    pytest -v -n auto -S
  9. Update FloPy version numbers with update_version.py

    develop

    The update_version.py script automates the process of updating the FloPy version number across the repository. It updates version.txt and propagates the change to flopy/version.py, CITATION.cff, README.md, and docs/PyPI_release.md.

    Behavior:

    • The script uses file locking to prevent desynchronization during writes.
    • If run without arguments, it only updates timestamps without changing the version number.

    Options:

    • --version or -v: Sets a new version number.
    • --get or -g: Retrieves the current version from version.txt without making changes.
    # Set the version to 3.3.6
    python scripts/update_version.py -v 3.3.6
    
    # Get the current version
    python scripts/update_version.py -g
  10. Manually publish a new version to Conda Forge

    develop

    If the automatic bot does not update the Conda distribution, follow these steps using a fork of conda-forge/flopy-feedstock:

    1. Download the *.tar.gz release from the GitHub releases page.
    2. Calculate the SHA256 checksum:
      openssl sha256 flopy-version.tar.gz
    3. Sync your fork with upstream flopy-feedstock:
      cd /path/to/your/flopy-feedstock_fork
      git fetch upstream
      git checkout master
      git reset --hard upstream/master
      git push origin master --force
    4. Rerender the repository using conda-smithy:
      conda smithy rerender
    5. Update the version number and the SHA256 checksum in the recipe/meta.yaml file.
    6. Commit and push to your fork, then create a Pull Request to the main conda-forge/flopy-feedstock repository.
    openssl sha256 flopy-version.tar.gz
    conda smithy rerender
  11. Create new FloPy tutorials and examples

    develop

    When contributing new examples, the filename determines how they are categorized in the documentation:

    • Tutorials: Filenames containing tutorial are assigned to the Tutorials page. They should demonstrate a single basic feature.
    • Examples: Filenames containing example are full-fledged examples, often demonstrating multiple features or complex workflows.

    Required Metadata Header

    All examples must include a jupytext header. You can generate a template by performing a round-trip conversion (script $\to$ notebook $\to$ script) using jupytext. The header must include at minimum:

    • section: The documentation section (use create_rstfiles.py to see available sections; defaults to "Miscellaneous").
    • authors: A list of the example's authors.

    Example header format:

    # ---
    # jupyter
    #   jupytext:
    #     ...
    #   kernelspec:
    #     ...
    #   metadata:
    #     section: ...
    #     authors:
    #       - name: ......
    # ---
    jupytext --from py --to ipynb .docs/Notebooks/your_example.py
    jupytext --from ipynb --to py .docs/Notebooks/your_example.ipynb
  12. Configure Visual Studio Code for FloPy development

    develop

    To ensure VSCode correctly uses your FloPy environment and activates it in integrated terminals, add the following to your settings.json. Replace /path/to/environment with the actual path to your environment's Python executable (which you can find by running where python in an activated terminal).

    {
        "python.defaultInterpreterPath": "/path/to/environment",
        "python.terminal.activateEnvironment": true
    }