diff --git a/.build_rtd_docs/Doxyfile b/.build_rtd_docs/Doxyfile index 95a4d26625d..8a65f959d6a 100644 --- a/.build_rtd_docs/Doxyfile +++ b/.build_rtd_docs/Doxyfile @@ -37,13 +37,13 @@ PROJECT_NAME = "MODFLOW 6" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = "version 6.5.0" +PROJECT_NUMBER = "version 6.6.0" # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. -PROJECT_BRIEF = "MODFLOW 6 Code Documentation" +PROJECT_BRIEF = "USGS Modular Hydrologic Model" # With the PROJECT_LOGO tag one can specify a logo or an icon that is included # in the documentation. The maximum height of the logo should not exceed 55 diff --git a/.build_rtd_docs/MAINPAGE.md b/.build_rtd_docs/MAINPAGE.md index 370b16a99f1..746c8c34bed 100644 --- a/.build_rtd_docs/MAINPAGE.md +++ b/.build_rtd_docs/MAINPAGE.md @@ -1,7 +1,7 @@ -# MODFLOW 6 Source Code Documentation +# Overview The documentation here is extracted from the source code by [doxygen](https://www.doxygen.nl/index.html). -The source code repository is hosted at https://github.com/MODFLOW-USGS/modflow6 where full details can be found. +The source code repository is hosted [on GitHub](https://github.com/MODFLOW-USGS/modflow6). -MODFLOW 6 usage documentation can be found at https://modflow6.readthedocs.io/en/latest/ +This documentation is intended for MODFLOW 6 contributors and users of the MODFLOW 6 library/API. MODFLOW 6 usage documentation can be found [on ReadTheDocs](https://modflow6.readthedocs.io/en/latest/). diff --git a/.build_rtd_docs/conf.py b/.build_rtd_docs/conf.py index 40b117a9f22..1fbbefc769d 100644 --- a/.build_rtd_docs/conf.py +++ b/.build_rtd_docs/conf.py @@ -1,3 +1,4 @@ +# ruff: noqa: E402 # Configuration file for the Sphinx documentation builder. # # This file only contains a selection of the most common options. For a full @@ -14,7 +15,7 @@ # documentation root, use os.path.abspath to make it absolute, like shown here. # import sys -from subprocess import Popen, PIPE +from subprocess import PIPE, Popen sys.path.insert(0, os.path.abspath(os.path.join("..", "doc"))) sys.path.insert(0, os.path.abspath(os.path.join("..", "distribution"))) @@ -23,12 +24,12 @@ on_rtd = os.environ.get("READTHEDOCS") == "True" # -- print current directory -print("Current Directory...'{}'".format(os.path.abspath(os.getcwd()))) +print(f"Current Directory...'{os.path.abspath(os.getcwd())}'") # -- clean up doxygen files ------------------------------------------------- dox_pths = ("_mf6io",) for dox_pth in dox_pths: - print("cleaning....{}".format(dox_pth)) + print(f"cleaning....{dox_pth}") for root, dirs, files in os.walk(dox_pth): for name in files: fpth = os.path.join(root, name) @@ -37,6 +38,7 @@ # -- Update the modflow 6 version ------------------------------------------- print("Update the modflow6 version") from update_version import update_version + update_version() # -- import version from doc/version.py ------------------------------------- @@ -56,6 +58,50 @@ # copy the file shutil.copy(src, dst) +# -- copy developer docs +dstdir = "_dev" +fpth = "DEVELOPER.md" +src = os.path.join("..", fpth) +dst = os.path.join(dstdir, fpth.lower()) +# clean up an existing _mf6run directory +if os.path.isdir(dstdir): + shutil.rmtree(dstdir) +# make the directory +os.makedirs(dstdir) +# copy the file +shutil.copy(src, dst) + +# -- copy contributor docs +fpth = "CONTRIBUTING.md" +src = os.path.join("..", fpth) +dst = os.path.join(dstdir, fpth.lower()) +shutil.copy(src, dst) + +# -- copy style guide +fpth = "styleguide.md" +src = os.path.join(fpth) +dst = os.path.join(dstdir, fpth) +shutil.copy(src, dst) + +# -- copy DFN spec +fpth = "readme.md" +src = os.path.join("..", "doc", "mf6io", "mf6ivar", fpth) +dst = os.path.join(dstdir, "dfn.md") +shutil.copy(src, dst) + +# -- build the deprecations table -------------------------------------------- +print("Build the deprecations markdown table") +pth = os.path.join("..", "doc", "mf6io", "mf6ivar") +args = (sys.executable, "deprecations.py") +# run the command +proc = Popen(args, stdout=PIPE, stderr=PIPE, cwd=pth) +stdout, stderr = proc.communicate() +if stdout: + print(stdout.decode("utf-8")) +if stderr: + print("Errors:") + print(stderr.decode("utf-8")) + # -- copy deprecations markdown --------------------------------------------- print("Copy the deprecations table") dstdir = "_mf6run" @@ -75,7 +121,8 @@ if stdout: print(stdout.decode("utf-8")) if stderr: - print("Errors:\n{}".format(stderr.decode("utf-8"))) + print("Errors:") + print(stderr.decode("utf-8")) # -- update the doxygen version number --------------------------------------- print("Update the Doxyfile with the latest version number") @@ -86,13 +133,13 @@ with open("Doxyfile", "w") as fp: for line in lines: if tag in line: - line = '{} = "version {}"\n'.format(tag, __version__) + line = f'{tag} = "version {__version__}"\n' fp.write(line) # -- Project information ----------------------------------------------------- -project = "MODFLOW 6 Program Documentation" -copyright = "2023, MODFLOW Development Team" +project = "MODFLOW 6" +copyright = "2024, MODFLOW Development Team" author = "MODFLOW Development Team" # -- Project version --------------------------------------------------------- @@ -126,6 +173,8 @@ # # Tell sphinx what the pygments highlight language should be. # highlight_language = 'fortran' +source_suffix = {".rst": "restructuredtext", ".md": "markdown"} + # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] diff --git a/.build_rtd_docs/dev.rst b/.build_rtd_docs/dev.rst new file mode 100644 index 00000000000..c9dc57173ed --- /dev/null +++ b/.build_rtd_docs/dev.rst @@ -0,0 +1,13 @@ +Developer Guide +--------------- + +This section includes developer instructions and conventions. + +.. toctree:: + :maxdepth: 1 + :glob: + + _dev/contributing.md + _dev/developer.md + _dev/styleguide.md + _dev/dfn.md diff --git a/.build_rtd_docs/index.rst b/.build_rtd_docs/index.rst index 813d5a4daff..35e9f2fcb5a 100644 --- a/.build_rtd_docs/index.rst +++ b/.build_rtd_docs/index.rst @@ -11,8 +11,9 @@ Contents: .. toctree:: :maxdepth: 2 - MODFLOW 6 Source Code Documentation - mf6io + API Reference _mf6run/run-time-comparison.md _mf6run/deprecations.md + mf6io + dev diff --git a/.build_rtd_docs/make.bat b/.build_rtd_docs/make.bat new file mode 100644 index 00000000000..7893348a1b7 --- /dev/null +++ b/.build_rtd_docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% + +:end +popd diff --git a/.build_rtd_docs/mf6io.rst b/.build_rtd_docs/mf6io.rst index cf1d21ffaa0..195248fc4ed 100644 --- a/.build_rtd_docs/mf6io.rst +++ b/.build_rtd_docs/mf6io.rst @@ -1,8 +1,9 @@ -MODFLOW 6 Input Guide ---------------------- +Input Guide +----------- -The latest version of the complete MODFLOW 6 input output guide can be found +The latest version of the complete MODFLOW 6 input/output guide can be found `here `_. +This section enumerates and describes MODFLOW 6 input files. Simulation ^^^^^^^^^^ @@ -44,6 +45,26 @@ Groundwater Transport _mf6io/gwt-* +Groundwater Energy Transport +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. toctree:: + :maxdepth: 1 + :glob: + + _mf6io/gwe-* + + +Particle Tracking +^^^^^^^^^^^^^^^^^ + +.. toctree:: + :maxdepth: 1 + :glob: + + _mf6io/prt-* + + Model Exchanges ^^^^^^^^^^^^^^^ diff --git a/.build_rtd_docs/styleguide.md b/.build_rtd_docs/styleguide.md new file mode 100644 index 00000000000..79523b12aea --- /dev/null +++ b/.build_rtd_docs/styleguide.md @@ -0,0 +1,380 @@ +# Fortran Style Guide + +The goal of this guide is to provide a standard for MODFLOW 6 contributors to follow, in pursuit of consistent, readable, well-organized, and unsurprising source code. + +MODFLOW 6 is written in Fortran — largely Fortran 2003, with sparse use of a few 2008 language features. This guide assumes familiarity with the Fortran language. + +## Amendments + +Suggestions to change or extend the style conventions are welcome. Suggestions should be accompanied by a good case for the change. Bear in mind that a goal of this guide is to minimize time spent thinking about questions of style. + +## Conventions + +```{contents} Table of Contents +:local: +``` +*** +### Modules +#### Use `implicit none` in all modules. + > In old FORTRAN variables types were implicitly assigned to variables depending on the variable name. + > It easy to create a bug using this old way because the developer is responsible of keeping track of what type each variable is. Using `implicit none` forces the developer to explicitly assign a type to a variable. This makes it possible to catch certain mistakes during the compilation step e.g. unintended type conversion +#### Make modules `private` by default. Mark `public` types and procedures explicitly. + > Instead of declaring everything public it is better to have it declared private by default and explicitly define what is public. + > This makes it clear to whom is using your module which types and procedures they may use. + > + > Furthermore as the developer of the module it also makes it clear which procedures are internal and you can change without affecting any external code. On the other hand if its public changes should be made with care. +#### Prefer explicitly specified imports with `use ..., only: ...`, rather than merely `use ...`. + > When only using the `use ...` syntax you pull in everything a module defines. This can cause name collision. Therefore always use the `use ..., only: ...` syntax + ```f90 + module SampleModule + ! don't + use ConstantsModule + + ! do + use ConstantsModule, only: DPI + end module SampleModule + ``` + +*** +### Types + +*** +### Procedures + +#### Don't end procedures with a `return` statement; use `return` only to return early. + > Adding a `return` statement is superfluous as the procedure will return anyway after the last line + ```f90 + ! don't + subroutine run_sample() + ! Some code + return + end subroutine + + ! do + subroutine run_sample() + ! Some code + end subroutine + ``` +#### Avoid `goto` statements. + > `goto` statements are something from the past. They are usually used to reach code based on a condition. If you want to achieve the same consider using: + - exit/continue in your loops, cases and if statements + - splitting your code in subroutines + - a loop + - putting conditional code in if else statements + - ... + +#### Specify precision for logicals, integers and reals with the data types defined in `src/Utilities/kind.f90`. + > This ensures that the same types are used throughout the code base + ```f90 + use KindModule, only: DP, I4B, LGP + + ! don't + logical :: boolean_var + integer :: integer_var + real(8) :: double_var + + ! do + logical(LGP) :: boolean_var + integer(I4B) :: integer_var + real(DP) :: double_var + ``` +#### Name type-bound procedures' first dummy argument `this`. A suitable docstring is `!< this instance`. + ```f90 + subroutine method(this) + ! don't + class(CustomType) :: this + end subroutine + + subroutine method(this) + ! do + class(CustomType) :: this !< this instance + end subroutine + ``` +#### Avoid deeply nested control structures where possible. + > Deeply nested structures makes it difficult for the reader to keep track of what is happening. Try to make the code as *flat* as possible. + ```f90 + ! don't + subroutine nested() + if (condition1) then + if (condition2) then + if (condition3) then + call procedure + end if + end if + end if + end subroutine nested + + ! do + subroutine flat() + if (.not. condition1) then return + if (.not. condition2) then return + if (.not. condition3) then return + + call procedure + end subroutine flat + ``` +#### Prefer verbose names, except where the meaning is obvious from context or precedent. E.g., well-known index variables (`i`, `j`, `m`, `n`). + > You're writing code for humans. Not for machines. Use clear names so it immediately becomes obvious what a variable means. + ```f90 + ! don't + List :: lst + HashTable :: ht + real(DP) :: t + + ! do + List :: list + HashTable :: hash_table + real(DP) :: time + ``` +#### Use named constants. Avoid [magic numbers](https://en.wikipedia.org/wiki/Magic_number_(programming)). + > Related to the rule above. Magic numbers make it difficult to understand code. What does a number mean? + ```f90 + real(DP) constant_velocity + real(DP) delta_time = 5.0 + real(DP) distance + + ! Don't. What does 1.0 mean? + distance = delta_time * 1.0 + + ! Do. It is clear what the number means + constant_velocity = 1.0 + distance = delta_time * constant_velocity + ``` + +*** +### Naming +#### Use `CamelCase` for source file names. +``` +- modflow + - src + - ExampleSourceFile.f90 +``` +#### Use `CamelCase` for module and derived type names. +```f90 +module SampleModule + + type :: SampleType + ... + end type SampleType + +end module SampleModule +``` + +#### Use a noun or noun phrase for module and derived type names. +A (derived) type is an object in object-oriented programming. And objects are described with nouns. The procedures in the type should be verbs and can be thought of actions that can be performed on/by/to the object + +#### Use `snake_case` for procedure names. +```f90 +subroutine display_sample_name() + ... +end subroutine +``` +#### Use a verb or verb phrase for procedure names. +Procedures should be thought of as actions performed on an object or arguments.As actions are described by verbs or verb phrases so must procedure names be named. + +#### End module names with `...Module`. +```f90 +module SampleModule + ... +end module SampleModule +``` + +#### Derived type names may, but need not, end with `...Type`. +```f90 +! This is good +type :: FirstSampleType + ... +end type + +! This as well +type :: SecondSampleType + ... +end type SecondSampleType +``` + +#### If a source file exists primarily to host a module, name the source file and module identically, except for trailing `...Module`. +```f90 +module SampleModule + ... +end module SampleModule +``` +``` +- modflow + - src + - Sample.f90 +``` +#### If a module exists primarily to host a type, name the module and type identically, except for trailing `...Module` and `...Type`. +```f90 +module SampleModule + + type :: SampleType + ... + end type SampleType + +end module SampleModule +``` + +#### Include the module/subroutine/function name in `end module`, `end subroutine` and `end function` statements. +```f90 +module SampleModule + + type :: SampleType + ... + end type SampleType + +contains + + subroutine sample_subroutine() + ... + end subroutine sample_subroutine + + function sample_function(this) result(res) + ... + end functions sample_function + +end module SampleModule +``` + +*** + +### Comments +#### Avoid empty comments. +```f90 +! don't + +! +! some comment +``` +```f90 +! do + +! some comment +``` +#### Avoid comments starting with `--`. +```f90 +! don't +! -- some comment + +! do +! some comment +``` + +*** + +### Formatting +#### Include blank lines between: + * module declaration and `use...` statements + * `use...` statements and procedure declarations + * derived type declaration and member variables + * member variables and `contains` statements +```f90 +module SampleModule + + use KindModule, only: DP + + type :: SampleType + real(DP) :: value + contains + procedure :: do_something + end type SampleType + +contains + + subroutine do_something(this) + ... + end subroutine add + +end module SampleModule +``` + +#### Prefer importing items used throughout a module with a module-scoped `use` statement, rather than separately in multiple procedures. +```f90 +! don't +module SampleModule + +contains + + subroutine do_something() + use KindModule, only: DP + ... + end subroutine add + + subroutine do_something_else() + use KindModule, only: DP + ... + end subroutine add + +end module SampleModule +``` +```f90 +! do +module SampleModule + + use KindModule, only: DP + +contains + + subroutine do_something() + ... + end subroutine add + + subroutine do_something_else() + ... + end subroutine add + +end module SampleModule +``` + +#### Use [Doxygen format](https://www.doxygen.nl/manual/docblocks.html#fortranblocks) for docstrings. For dummy arguments, use either `@param ...` above the signature or `!< ...` next to the dummy argument. +```f90 +!> Description of the procedure. +!! +!! @param parameter2 information about parameter2 +!! @param parameter3 information about parameter3 +!! @todo Handle special case +subroutine intrestbuild(parameter1, parameter2, parameter3) + implicit none + integer(I4B), intent(in) :: parameter1 !< information about parameter1 + integer(I4B), intent(in) :: parameter2 + integer(I4B), intent(out) :: parameter3 + + ... + +end subroutine +``` + +*** + +## Sample Module + +Below is a minimal module demonstrating some (but not all) of the conventions. + +```f90 +module SampleModule + + use KindModule, only: DP, I4B, LGP + use ConstantsModule, only: DPI + + implicit none + private + public :: run_sample + +contains + + subroutine run_sample(verbose) + logical(LGP), intent(in) :: verbose + integer(I4B) :: answer + real(DP) :: pi + + answer = 42 + pi = DPI + + if (verbose) then + print *, 'pi: ', pi + print *, 'answer to the ultimate question of life,'& + ' the universe, and everything: ', answer + end if + end subroutine run_sample + +end module SampleModule +``` diff --git a/.codespell.ignore b/.codespell.ignore index c0a87d7fc47..30296cf990b 100644 --- a/.codespell.ignore +++ b/.codespell.ignore @@ -1,4 +1,4 @@ -alph +Alph wel nam gage @@ -7,13 +7,20 @@ delt lke ist inout +fo +nd ot -initialx -initialy -initialz +initialY +localy +indx iterm dum shft lsat +ahd thi thckstrt +rin +checkin +exchng +welp diff --git a/.codespellrc b/.codespellrc new file mode 100644 index 00000000000..307512d86b0 --- /dev/null +++ b/.codespellrc @@ -0,0 +1,3 @@ +[codespell] +skip = *.pdf,*.grb,*.bib,*.bst,*.log,./builddir,./src/Utilities/Libraries,./utils/mf5to6,./doc/ReleaseNotes/previous +ignore-words = .codespell.ignore diff --git a/.doc/_static/CustomDoxygen.css b/.doc/_static/CustomDoxygen.css index dceb02cc92a..26c8d074c6b 100644 --- a/.doc/_static/CustomDoxygen.css +++ b/.doc/_static/CustomDoxygen.css @@ -331,7 +331,7 @@ table.directory { line-height: 36px; background-color: #7fbdff; } -/* item list on botton left */ +/* item list on bottom left */ .navpath li.navelem a { height: 32px; diff --git a/.doc/conf.py b/.doc/conf.py index 8ed07df6dda..79e6f19bb41 100644 --- a/.doc/conf.py +++ b/.doc/conf.py @@ -29,9 +29,9 @@ src = os.path.join(src_pth, on_dir) dst = os.path.join(".", on_dir) if os.path.exists(dst): - print("deleting...{}".format(dst)) + print(f"deleting...{dst}") shutil.rmtree(dst) - print("copying {} -> {}".format(src, dst)) + print(f"copying {src} -> {dst}") shutil.copytree(src, dst) # copy files @@ -40,16 +40,16 @@ src = os.path.join(src_pth, file_name) dst = os.path.join(".", file_name) if os.path.exists(dst): - print("deleting...{}".format(dst)) + print(f"deleting...{dst}") os.remove(dst) - print("copying {} -> {}".format(src, dst)) + print(f"copying {src} -> {dst}") shutil.copy(src, dst) # -- Project information ----------------------------------------------------- -project = "MODFLOW 6 Program Documentation" -copyright = "2023, MODFLOW Development Team" +project = "MODFLOW 6" +copyright = "2024, MODFLOW Development Team" author = "MODFLOW Development Team" # -- General configuration --------------------------------------------------- @@ -88,7 +88,7 @@ rtds_action_github_token = os.environ.get("GITHUB_TOKEN", None) # set master doc for readthedoce -master_doc = 'index' +master_doc = "index" # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 00000000000..c38610503fb --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,41 @@ +# apply fprettify formatting (#956) +41e98a24cec6d3607138558fa538621191260efa + +# apply fprettify formatting (#957) +c033fc85713770ace7d51f3c382257bc90d9932f + +# apply fprettify formatting (#960) +571dcfd5cd439ba7129ed86b6e54e6e0c7340d35 + +# apply fprettify formatting (#961) +cc444d0364f97e47c965b91efd6b480d66ea2105 + +# apply fprettify formatting (#963) +04e82dd660541b3fa61b9cfe3343a827698f113a + +# apply fprettify formatting (#969) +b063109202645a13a2f6d8b9799048c304e525d9 + +# apply fprettify formatting (#974) +9514eb46c14f0d4f4860fbfb0eb96c2606ac597f + +# apply fprettify formatting (#975) +c3f415362edd6a8e033204967281fd10061dacf8 + +# apply fprettify formatting (#980) +ff1f8e596680ce1a5bdad589b80b2746bc6dca55 + +# apply fprettify formatting (#984) +d56a12e0db8ff9d052b7ef9d7157506528e1a70e + +# apply fprettify formatting (#985) +9f7c07aea29d55f9c0ef2a61f62bc15d45321695 + +# run ruff lint and format on python files in repo (#1936) +9d55d586439b832c33feb196718a6122973dc6aa + +# reformat Python code with line length = 88 (#2056) +f6c3a55ea72065ba1ce8540d1fd3c051696df1f1 + +# reformat multi-line statements (#2070) +cc7f930b961345536529942fc57db0c515a1f7fc diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000000..18be48ae05d --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,18 @@ +Replace this paragraph with a written description of the pull request. Include images and files as necessary to help with the documentation. Descriptions for trivial and minor pull requests should be brief. + +Checklist of items for pull request + +- [ ] Replaced section above with description of pull request +- [ ] Closed issue #xxxx +- [ ] Referenced issue or pull request #xxxx +- [ ] Added new test or modified an existing test +- [ ] Ran `ruff` on new and modified python scripts in .doc, autotests, doc, distribution, pymake, and utils subdirectories. +- [ ] Formatted new and modified Fortran source files with `fprettify` +- [ ] Added doxygen comments to new and modified procedures +- [ ] Updated meson files, makefiles, and Visual Studio project files for new source files +- [ ] Updated [definition files](/MODFLOW-USGS/modflow6/tree/develop/doc/mf6io/mf6ivar) +- [ ] Updated [develop.tex](/MODFLOW-USGS/modflow6/doc/ReleaseNotes/develop.tex) with a plain-language description of the bug fix, change, feature; required for changes that may affect users +- [ ] Updated [input and output guide](/MODFLOW-USGS/modflow6/doc/mf6io) +- [ ] Removed checklist items not relevant to this pull request + +For additional information see [instructions for contributing](/MODFLOW-USGS/modflow6/.github/CONTRIBUTING.md) and [instructions for developing](/MODFLOW-USGS/modflow6/.github/DEVELOPER.md). \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md deleted file mode 100644 index 1affcbe0ed5..00000000000 --- a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +++ /dev/null @@ -1,8 +0,0 @@ -Feel free to remove check-list items that aren't relevant to your change. - -- [ ] Closes #xxxx -- [ ] Passed autotests -- [ ] Formatted source files with `fprettify` -- [ ] Updated definition (*.dfn) files with new or modified options -- [ ] Described new options, features or behavior changes in release notes -- [ ] Updated meson files, makefiles, and Visual Studio project files if new source files added \ No newline at end of file diff --git a/.github/actions/build-par-win/action.yml b/.github/actions/build-extended-win/action.yml similarity index 50% rename from .github/actions/build-par-win/action.yml rename to .github/actions/build-extended-win/action.yml index abc9a39b19d..97576f8d95d 100644 --- a/.github/actions/build-par-win/action.yml +++ b/.github/actions/build-extended-win/action.yml @@ -1,8 +1,11 @@ -name: Build parallel MF6 (Windows) -description: Build parallel MODFLOW 6 on Windows +name: Build Extended MF6 (Windows) +description: Build Extended MODFLOW 6 on Windows runs: using: "composite" steps: + # first NetCDF, PETSc cygwin installation forces a different bash shell upon us... + - name: Setup NetCDF + uses: ./modflow6/.github/actions/build-netcdf-win - name: Setup PETSc uses: ./modflow6/.github/actions/build-petsc-win @@ -10,11 +13,11 @@ runs: - name: Build modflow6 shell: cmd run: | - unix2dos -n "%GITHUB_WORKSPACE%\modflow6\.github\common\compile_modflow6.bat" "%TEMP%\compile_modflow6.bat" - "%ONEAPI_ROOT%\setvars.bat" intel64 vs2022 && "%TEMP%\compile_modflow6.bat" + unix2dos -n "%GITHUB_WORKSPACE%\modflow6\.github\common\compile_modflow6_extended.bat" "%TEMP%\compile_modflow6_extended.bat" + "%ONEAPI_ROOT%\setvars.bat" intel64 vs2022 && "%TEMP%\compile_modflow6_extended.bat" - name: Show Meson logs if: failure() shell: bash working-directory: modflow6 - run: cat builddir/meson-logs/meson-log.txt \ No newline at end of file + run: cat builddir/meson-logs/meson-log.txt diff --git a/.github/actions/build-netcdf-win/action.yml b/.github/actions/build-netcdf-win/action.yml new file mode 100644 index 00000000000..14474bd8f36 --- /dev/null +++ b/.github/actions/build-netcdf-win/action.yml @@ -0,0 +1,42 @@ +name: Build NetCDF (Windows) +description: Build NetCDF on Windows +runs: + using: "composite" + steps: + - name: Convert line endings + shell: cmd + run: | + unix2dos -n "%GITHUB_WORKSPACE%\modflow6\.github\common\compile_netcdf.bat" "%TEMP%\compile_netcdf.bat" + + - name: Install latest cmake and ninja + uses: lukka/get-cmake@latest + with: + cmakeVersion: latest + ninjaVersion: latest + + - name: Setup 7-zip + uses: milliewalky/setup-7-zip@v1 + + - name: Download NetCDF-C + shell: bash + run: | + mkdir -p netcdf/netCDF4.9.2-NC4-64 + cd netcdf/netCDF4.9.2-NC4-64 + curl https://downloads.unidata.ucar.edu/netcdf-c/4.9.2/netCDF4.9.2-NC4-64.exe -O -J + 7z x netCDF4.9.2-NC4-64.exe -aou + + - name: Download NetCDF-Fortran + shell: bash + run: | + mkdir -p netcdf/netcdf-fortran-4.6.1/build + cd netcdf/netcdf-fortran-4.6.1 + curl https://downloads.unidata.ucar.edu/netcdf-fortran/4.6.1/netcdf-fortran-4.6.1.zip -O -J + unzip netcdf-fortran-4.6.1.zip + + - name: Setup oneAPI + uses: ./modflow6/.github/actions/setup-par-oneapi + + - name: Build NetCDF + shell: cmd + run: | + "%ONEAPI_ROOT%\setvars.bat" intel64 vs2022 && "%TEMP%\compile_netcdf.bat" diff --git a/.github/actions/setup-par-oneapi/action.yml b/.github/actions/setup-par-oneapi/action.yml index bda95818cbf..fe3b493dd65 100644 --- a/.github/actions/setup-par-oneapi/action.yml +++ b/.github/actions/setup-par-oneapi/action.yml @@ -24,7 +24,7 @@ runs: shell: bash if: steps.oneapi-cache.outputs.cache-hit != 'true' run: | - url="https://registrationcenter-download.intel.com/akdlm/IRC_NAS/5cb30fb9-21e9-47e8-82da-a91e00191670/w_BaseKit_p_2024.0.1.45_offline.exe" + url="https://registrationcenter-download.intel.com/akdlm/IRC_NAS/7dff44ba-e3af-4448-841c-0d616c8da6e7/w_BaseKit_p_2024.1.0.595_offline.exe" cmp="intel.oneapi.win.mkl.devel" "$GITHUB_WORKSPACE/modflow6/.github/common/install_intel_windows.bat" $url $cmp rm -rf $TEMP/webimage.exe @@ -34,7 +34,7 @@ runs: shell: bash if: steps.oneapi-cache.outputs.cache-hit != 'true' run: | - url="https://registrationcenter-download.intel.com/akdlm/IRC_NAS/7a6db8a1-a8b9-4043-8e8e-ca54b56c34e4/w_HPCKit_p_2024.0.1.35_offline.exe" + url="https://registrationcenter-download.intel.com/akdlm/IRC_NAS/c95a3b26-fc45-496c-833b-df08b10297b9/w_HPCKit_p_2024.1.0.561_offline.exe" cmp="intel.oneapi.win.cpp-dpcpp-common:intel.oneapi.win.ifort-compiler:intel.oneapi.win.mpi.devel" "$GITHUB_WORKSPACE/modflow6/.github/common/install_intel_windows.bat" $url $cmp rm -rf $TEMP/webimage.exe diff --git a/.github/actions/test-par-win/action.yml b/.github/actions/test-extended-win/action.yml similarity index 72% rename from .github/actions/test-par-win/action.yml rename to .github/actions/test-extended-win/action.yml index 27e5e274223..d090e24a354 100644 --- a/.github/actions/test-par-win/action.yml +++ b/.github/actions/test-extended-win/action.yml @@ -1,11 +1,10 @@ -name: Test parallel MF6 (Windows) -description: Build and test parallel MODFLOW 6 on Windows +name: Test extended MF6 (Windows) +description: Build and test extended MODFLOW 6 on Windows runs: using: "composite" steps: - - name: Build MF6 parallel - uses: ./modflow6/.github/actions/build-par-win + uses: ./modflow6/.github/actions/build-extended-win - name: Update flopy working-directory: modflow6 @@ -22,21 +21,21 @@ runs: - name: Convert unix2dos shell: cmd run: | - unix2dos -n "%GITHUB_WORKSPACE%\modflow6\.github\common\test_modflow6.bat" "%TEMP%\test_modflow6.bat" + unix2dos -n "%GITHUB_WORKSPACE%\modflow6\.github\common\test_modflow6_extended.bat" "%TEMP%\test_modflow6_extended.bat" - - name: Test programs + - name: Test programs (extended) if: github.ref_name != 'master' shell: cmd env: REPOS_PATH: ${{ github.workspace }} run: | - "%ONEAPI_ROOT%\setvars.bat" intel64 vs2022 && "%TEMP%\test_modflow6.bat" + "%ONEAPI_ROOT%\setvars.bat" intel64 vs2022 && "%TEMP%\test_modflow6_extended.bat" - - name: Test programs + - name: Test programs (extended) if: github.ref_name == 'master' shell: cmd env: REPOS_PATH: ${{ github.workspace }} MARKERS: not developmode run: | - "%ONEAPI_ROOT%\setvars.bat" intel64 vs2022 && "%TEMP%\test_modflow6.bat" + "%ONEAPI_ROOT%\setvars.bat" intel64 vs2022 && "%TEMP%\test_modflow6_extended.bat" diff --git a/.github/actions/test-par/action.yml b/.github/actions/test-extended/action.yml similarity index 50% rename from .github/actions/test-par/action.yml rename to .github/actions/test-extended/action.yml index b14c8e78397..24638edb8f5 100644 --- a/.github/actions/test-par/action.yml +++ b/.github/actions/test-extended/action.yml @@ -1,9 +1,8 @@ -name: Test parallel MF6 -description: Build and test parallel MODFLOW 6 +name: Test Extended MF6 +description: Build and test Extended MODFLOW 6 runs: using: "composite" steps: - - name: Setup GNU Fortran uses: fortran-lang/setup-fortran@v1 with: @@ -11,48 +10,60 @@ runs: version: 13 - name: Checkout PETSc + if: runner.os == 'Linux' uses: actions/checkout@v4 with: repository: petsc/petsc path: petsc ref: release - - name: Configure environment - if: runner.os == 'Linux' - shell: bash - run: | - echo "PKG_CONFIG_PATH=$GITHUB_WORKSPACE/petsc/linux-gnu/lib/pkgconfig" >> $GITHUB_ENV - echo "$GITHUB_WORKSPACE/petsc/linux-gnu/bin" >> $GITHUB_PATH + - name: Checkout PETSc + if: runner.os == 'macOS' + uses: actions/checkout@v4 + with: + repository: petsc/petsc + path: petsc + ref: v3.22.1 - name: Configure environment - if: runner.os == 'macOS' shell: bash run: | - echo "PKG_CONFIG_PATH=$GITHUB_WORKSPACE/petsc/arch-darwin-gcc/lib/pkgconfig" >> $GITHUB_ENV - echo "$GITHUB_WORKSPACE/petsc/arch-darwin-gcc/bin" >> $GITHUB_PATH + echo "PKG_CONFIG_PATH=$GITHUB_WORKSPACE/petsc/arch-gcc-opt/lib/pkgconfig" >> $GITHUB_ENV + echo "$GITHUB_WORKSPACE/petsc/arch-gcc-opt/bin" >> $GITHUB_PATH - name: Configure PETSc - if: runner.os == 'Linux' shell: bash working-directory: petsc run: | sudo wget -P $GITHUB_WORKSPACE/petsc https://download.open-mpi.org/release/open-mpi/v5.0/openmpi-5.0.2.tar.gz - sudo ./configure PETSC_ARCH=linux-gnu --download-fblaslapack --download-openmpi=$GITHUB_WORKSPACE/petsc/openmpi-5.0.2.tar.gz + sudo ./configure PETSC_ARCH=arch-gcc-opt --download-fblaslapack --download-openmpi=$GITHUB_WORKSPACE/petsc/openmpi-5.0.2.tar.gz --with-debugging=0 sudo make all - - name: Configure PETSc + - name: Install netcdf + if: runner.os == 'Linux' + shell: bash + run: | + sudo apt-get update + sudo apt-get install build-essential \ + libnetcdf-dev \ + libnetcdff-dev \ + netcdf-bin + nc-config --all + nf-config --all + + - name: Install netcdf if: runner.os == 'macOS' shell: bash - working-directory: petsc run: | - sudo ./configure PETSC_DIR="$GITHUB_WORKSPACE/petsc" PETSC_ARCH=arch-darwin-gcc --download-fblaslapack --download-openmpi --with-debugging=0 - sudo make all + brew install netcdf-fortran + nc-config --all + nf-config - name: Build modflow6 shell: bash working-directory: modflow6 run: | - pixi run setup -Dparallel=true builddir + pixi run setup -Dextended=true builddir pixi run build builddir pixi run test builddir @@ -74,9 +85,24 @@ runs: GITHUB_TOKEN: ${{ github.token }} run: pixi run get-exes - - name: Test programs + - name: Test programs (macOS) + if: runner.os == 'macOS' + shell: bash + working-directory: modflow6 + env: + REPOS_PATH: ${{ github.workspace }} + run: | + otool -L bin/libmf6.dylib + echo $DYLD_LIBRARY_PATH + pixi run autotest --parallel --netcdf -k "test_par or test_netcdf" + + - name: Test programs (Linux) + if: runner.os != 'macOS' shell: bash working-directory: modflow6 env: REPOS_PATH: ${{ github.workspace }} - run: pixi run autotest --parallel -k "test_par" + run: | + ldd bin/libmf6.so + echo $LD_LIBRARY_PATH + pixi run autotest --parallel --netcdf -k "test_par or test_netcdf" diff --git a/.github/common/check_format.py b/.github/common/check_format.py index e9a49bcdeb0..733909898f7 100644 --- a/.github/common/check_format.py +++ b/.github/common/check_format.py @@ -3,10 +3,10 @@ import sys import timeit from itertools import repeat -from queue import Empty +from multiprocessing import Manager, Pool, cpu_count from pathlib import Path +from queue import Empty from subprocess import run -from multiprocessing import cpu_count, Pool, Manager PROJ_ROOT = Path(__file__).parents[2] @@ -20,11 +20,11 @@ PROJ_ROOT / "src" / "Utilities" / "Libraries" / "sparskit2", PROJ_ROOT / "utils" / "mf5to6", PROJ_ROOT / "utils" / "zonebudget" / "msvs", - PROJ_ROOT / "msvs" + PROJ_ROOT / "msvs", ] # exclude these files from checks -excludefiles = [] +excludefiles = [PROJ_ROOT / "src" / "Idm" / "gwf-stoidm.f90"] # commands fprettify = "fprettify -c .fprettify.yaml" diff --git a/.github/common/check_spelling.py b/.github/common/check_spelling.py deleted file mode 100644 index 228104b10d1..00000000000 --- a/.github/common/check_spelling.py +++ /dev/null @@ -1,135 +0,0 @@ -import argparse -import os -import sys -import timeit -from itertools import repeat -from queue import Empty -from pathlib import Path -from subprocess import run -from multiprocessing import cpu_count, Pool, Manager - -PROJ_ROOT = Path(__file__).parents[2] - -# exclude these directories from checks -excludedirs = [ - PROJ_ROOT / ".pixi", - PROJ_ROOT / "autotest" / ".pytest_cache", - PROJ_ROOT / "src" / "Utilities" / "Libraries" / "blas", - PROJ_ROOT / "src" / "Utilities" / "Libraries" / "daglib", - PROJ_ROOT / "src" / "Utilities" / "Libraries" / "rcm", - PROJ_ROOT / "src" / "Utilities" / "Libraries" / "sparsekit", - PROJ_ROOT / "src" / "Utilities" / "Libraries" / "sparskit2", - PROJ_ROOT / "srcbmi" / "latex", - PROJ_ROOT / "utils" / "mf5to6", -] - -# exclude these files from checks -excludefiles = [] - -# commands -codespell = "codespell --ignore-words=.codespell.ignore" - - -def excluded(path) -> bool: - path = Path(path) - for f in excludefiles: - if os.path.exists(f) and os.path.samefile(path, f): - return True - for d in excludedirs: - if os.path.exists(d) and path.is_relative_to(d): - return True - return False - - -def check_spelling(path, lock, checks, failures, write_changes=False, verbose=False): - path = Path(path) - if verbose: - print(f"Checking spelling: {path}") - - wc = "-w" if write_changes else "" - cmd = f"{codespell} {wc} {path}" - result = run(cmd, capture_output=True, shell=True) - if result.stdout or result.stderr: - failures.put(path) - - with lock: - checks.value += 1 - - -def report(checks, failures, duration: float) -> bool: - def pop(q): - return q.get(block=False) - - n_failures = failures.qsize() - success = n_failures == 0 - print(f"Checked spelling for {checks.value} files in {duration:.4f}s") - - if n_failures > 0: - success = False - stats = f"failures: {n_failures} \\" - hr = "".join(repeat("_", len(stats) - 1)) - print(f"{hr}\n{stats}") - while True: - try: - print(f"{codespell} {pop(failures)}") - except Empty: - break - - print() - return success - - -if __name__ == "__main__": - start = timeit.default_timer() - parser = argparse.ArgumentParser("MODFLOW 6 spell check verification") - parser.add_argument( - "-p", - "--path", - help="path to file or directory", - default=PROJ_ROOT, - ) - parser.add_argument( - "-e", - "--extension", - help="file extensions to check", - action="append", - default=[".[fF]9[05]", ".dfn", ".tex", ".md"], - ) - parser.add_argument( - "-w", - "--write-changes", - help="write changes in place if possible", - action="store_true", - default=False, - ) - parser.add_argument( - "-v", "--verbose", action="store_true", help="verbose", default=False - ) - args = parser.parse_args() - path = Path(args.path).expanduser().absolute() - assert path.exists(), f"Path not found: {path}" - extensions = args.extension - write = args.write_changes - verbose = args.verbose - - # shared state - manager = Manager() - lock = manager.Lock() - checks = manager.Value("checks", 0) - failures = manager.Queue() - - if path.is_file(): - check_spelling(path, lock, checks, failures, write, verbose) - else: - with Pool(cpu_count()) as pool: - files = [] - for ext in extensions: - files.extend([str(p) for p in path.rglob(f"*{ext}") if not excluded(p)]) - if verbose: - msg = f"Checking {len(files)} files in directory: {path}" - print(msg) - print("".join(repeat("-", len(msg)))) - pool.starmap(check_spelling, [(f, lock, checks, failures, write, verbose) for f in files]) - - stop = timeit.default_timer() - sys.exit(0 if report(checks, failures, stop - start) else 1) diff --git a/.github/common/check_vfproj.py b/.github/common/check_vfproj.py index bd570c55fd7..6c1e8eade7c 100644 --- a/.github/common/check_vfproj.py +++ b/.github/common/check_vfproj.py @@ -4,7 +4,6 @@ from pathlib import Path from pprint import pformat - PROJ_ROOT = Path(__file__).parents[2] diff --git a/.github/common/compile_modflow6.bat b/.github/common/compile_modflow6_extended.bat similarity index 69% rename from .github/common/compile_modflow6.bat rename to .github/common/compile_modflow6_extended.bat index fa61f33885f..e95e0c1b334 100644 --- a/.github/common/compile_modflow6.bat +++ b/.github/common/compile_modflow6_extended.bat @@ -1,5 +1,5 @@ set FC=ifort cd "%GITHUB_WORKSPACE%\modflow6" -pixi run setup -Dparallel=true builddir +pixi run setup -Dextended=true builddir pixi run build builddir pixi run test builddir diff --git a/.github/common/compile_netcdf.bat b/.github/common/compile_netcdf.bat new file mode 100644 index 00000000000..94c18853332 --- /dev/null +++ b/.github/common/compile_netcdf.bat @@ -0,0 +1,11 @@ +cd "%GITHUB_WORKSPACE%\netcdf\netcdf-fortran-4.6.1\build" + +:: build/install static libs +cmake --fresh -G Ninja -DCMAKE_Fortran_COMPILER="C:/Program Files (x86)/Intel/oneAPI/compiler/latest/bin/ifort.exe" -DCMAKE_BUILD_TYPE=Release -DNETCDF_C_LIBRARY="%GITHUB_WORKSPACE%/netcdf/netCDF4.9.2-NC4-64/lib/netcdf.lib" -DNETCDF_C_INCLUDE_DIR="%GITHUB_WORKSPACE%/netcdf/netCDF4.9.2-NC4-64/include" -DBUILD_SHARED_LIBS=0 -DCMAKE_INSTALL_PREFIX="%GITHUB_WORKSPACE%/netcdf/netcdf-fortran-4.6.1/build" ../netcdf-fortran-4.6.1 +cmake --build . +cmake –-install . + +:: build/install shared libs +cmake --fresh -G Ninja -DCMAKE_Fortran_COMPILER="C:/Program Files (x86)/Intel/oneAPI/compiler/latest/bin/ifort.exe" -DCMAKE_BUILD_TYPE=Release -DNETCDF_C_LIBRARY="%GITHUB_WORKSPACE%/netcdf/netCDF4.9.2-NC4-64/lib/netcdf.lib" -DNETCDF_C_INCLUDE_DIR="%GITHUB_WORKSPACE%/netcdf/netCDF4.9.2-NC4-64/include" -DBUILD_SHARED_LIBS=1 -DCMAKE_INSTALL_PREFIX="%GITHUB_WORKSPACE%/netcdf/netcdf-fortran-4.6.1/build" ../netcdf-fortran-4.6.1 +cmake --build . +cmake –-install . diff --git a/.github/common/test_modflow6.bat b/.github/common/test_modflow6.bat deleted file mode 100644 index 2707f6d8c83..00000000000 --- a/.github/common/test_modflow6.bat +++ /dev/null @@ -1,4 +0,0 @@ -cd "%GITHUB_WORKSPACE%\modflow6\autotest" -where libpetsc.dll -ldd ..\bin\mf6 -pixi run autotest --parallel -k "test_par" -m "%MARKERS%" diff --git a/.github/common/test_modflow6_extended.bat b/.github/common/test_modflow6_extended.bat new file mode 100644 index 00000000000..337e8514f63 --- /dev/null +++ b/.github/common/test_modflow6_extended.bat @@ -0,0 +1,2 @@ +cd "%GITHUB_WORKSPACE%\modflow6\autotest" +pixi run autotest -m "%MARKERS%" --netcdf --parallel \ No newline at end of file diff --git a/.github/common/update_compat_tables.py b/.github/common/update_compat_tables.py index 59255741806..e5aab0f1bad 100644 --- a/.github/common/update_compat_tables.py +++ b/.github/common/update_compat_tables.py @@ -27,7 +27,7 @@ ct = ( "{}{}" ) diff --git a/.github/common/update_fortran_style.py b/.github/common/update_fortran_style.py deleted file mode 100644 index 95b49a5c19c..00000000000 --- a/.github/common/update_fortran_style.py +++ /dev/null @@ -1,213 +0,0 @@ -import argparse -import string -from itertools import repeat -from multiprocessing import cpu_count, Pool -from pathlib import Path - -from fprettify.fparse_utils import InputStream - -ALPHANUMERICS = set(string.ascii_letters + string.digits) - - -def join_comments(comments) -> str: - return "".join([c for c in comments if any(c)]) - - -class Rules: - @staticmethod - def separate_lines(path): - """Define dummy arguments, local variables, and procedure declarations on separate lines.""" - - flines = [] - with open(path, "r") as f: - stream = InputStream(f) - while 1: - line, comment, lines = stream.next_fortran_line() - if not lines: - break - line = line.rstrip() - parts = line.rpartition("::") - comment = join_comments(comment) - - if ( - not parts[1] - or "procedure" in parts[0] - or parts[0].strip().startswith("use") - ): - flines.extend(lines) - continue - - indent = "".join(repeat(" ", len(lines[0]) - len(lines[0].lstrip()))) - quals = [q.strip() for q in parts[0].split(",")] # qualifiers - vars = [v.strip() for v in parts[2].split(",")] # variable names - - if not line: - continue - if ( - (len(parts[0]) == 0 and len(parts[1]) == 0) - or ("(" in parts[2] or ")" in parts[2]) - or len(vars) == 1 - or "parameter" in parts[0] - ): - flines.extend(lines) - else: - for s in vars: - if s == "&": - continue - l = indent + ", ".join(quals) - l += f" :: {s}" - flines.append(l + comment) - - with open(path, "w") as f: - for line in flines: - f.write(line.rstrip() + "\n") - - @staticmethod - def trailing_returns(path): - """Remove return statements (and corresponding comments) at the end of routines.""" - - flines = [] - with open(path, "r") as f: - stream = InputStream(f) - while 1: - line, comment, lines = stream.next_fortran_line() - if not lines: - break - line = line.rstrip() - comment = join_comments(comment) - - if comment.strip().lower().replace("-", "").replace(" ", "") in [ - "!return" - ]: - continue - elif "end subroutine" in line or "end function" in line: - for i, fl in enumerate(reversed(flines)): - l = fl.strip() - if not any(l): - continue - elif l == "return": - del flines[len(flines) - i - 1] - break - flines.extend(lines) - - with open(path, "w") as f: - for line in flines: - f.write(line.rstrip() + "\n") - - @staticmethod - def cleanup_comments(path): - """ - Remove empty comments (containing only '!', or '!' followed by some number of '-' or '='), - remove double dashes from beginnings of comments (e.g., '! -- comment' becomes '! comment'), - remove 'SPECIFICATION' comment lines, and make internal comment spacing consistent (one space - after '!' before text begins). - """ - - flines = [] - with open(path, "r") as f: - stream = InputStream(f) - while 1: - line, comment, lines = stream.next_fortran_line() - if not lines: - break - line = line.rstrip() - comment = join_comments(comment) - nspaces = len(lines[0]) - len(lines[0].lstrip()) - indent = "".join(repeat(" ", nspaces)) - - if comment.startswith("#"): - # preprocessor directives - flines.extend(lines) - elif not any(line): - if any(pattern in comment for pattern in ["!!", "!<", "!>"]): - flines.extend(lines) - elif "SPECIFICATIONS" in comment: - continue - elif any(set(comment) & ALPHANUMERICS): - comment = comment.strip().replace("--", "") - i = 0 - for c in comment: - if c.isdigit() or c.isalnum(): - break - i += 1 - comment = f"! {comment[i:]}" - flines.append(indent + comment) - elif "-" in comment or "*" in comment: - continue - else: - flines.append("") - else: - flines.extend(lines) - - with open(path, "w") as f: - for line in flines: - f.write(line.rstrip() + "\n") - - -def reformat( - path, - separate_lines, - trailing_returns, - cleanup_comments, -): - if separate_lines: - Rules.separate_lines(path) - if trailing_returns: - Rules.trailing_returns(path) - if cleanup_comments: - Rules.cleanup_comments(path) - - -if __name__ == "__main__": - parser = argparse.ArgumentParser( - """ - Modify MODFLOW 6 Fortran source code, either writing to stdout or - overwriting the input file. Options are provided for several code - styles. - """ - ) - parser.add_argument("path") - parser.add_argument( - "--separate-lines", - action="store_true", - default=True, - required=False, - help="Define dummy arguments, local variables, and procedure declarations on separate lines.", - ) - parser.add_argument( - "--trailing-returns", - action="store_true", - default=True, - required=False, - help="Remove return statements (and corresponding comments) at the end of routines.", - ) - parser.add_argument( - "--cleanup-comments", - action="store_true", - default=True, - required=False, - help="Remove empty comments (containing only '!', or '!' followed by some number of '-' or '='), remove double dashes from beginnings of comments (e.g., '! -- comment' becomes '! comment'), remove 'SPECIFICATION' comment lines, and make internal comment spacing consistent (one space after '!' before text begins).", - ) - args = parser.parse_args() - - # parse path - path = Path(args.path).expanduser().absolute() - assert path.exists(), f"Path not found: {path}" - - # parse rules - sl = args.separate_lines - tr = args.trailing_returns - cc = args.cleanup_comments - - # reformat - if path.is_file(): - reformat( - path=Path(args.path).expanduser().absolute(), - separate_lines=sl, - trailing_returns=tr, - cleanup_comments=cc, - ) - else: - with Pool(cpu_count()) as pool: - files = [p for p in path.rglob("*.f90") if p.is_file()] - pool.starmap(reformat, [(f, sl, tr, cc) for f in files]) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 37e705102a6..b5c74f065ec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,39 +2,39 @@ name: MODFLOW 6 continuous integration on: push: paths-ignore: - - '**.md' - - '**.pdf' - - '**.tex' - - '**.jpg' - - '**.jpeg' - - '**.png' - - '**.bbl' - - '**.bib' - - 'doc/**.dat' - - 'doc/**.ipynb' - - 'doc/**.py' - - 'doc/**.sh' - - 'doc/**.xlsx' - - '.hpc/**' + - "**.md" + - "**.pdf" + - "**.tex" + - "**.jpg" + - "**.jpeg" + - "**.png" + - "**.bbl" + - "**.bib" + - "doc/**.dat" + - "doc/**.ipynb" + - "doc/**.py" + - "doc/**.sh" + - "doc/**.xlsx" + - ".hpc/**" pull_request: branches: - master - develop paths-ignore: - - '**.md' - - '**.pdf' - - '**.tex' - - '**.jpg' - - '**.jpeg' - - '**.png' - - '**.bbl' - - '**.bib' - - 'doc/**.dat' - - 'doc/**.ipynb' - - 'doc/**.py' - - 'doc/**.sh' - - 'doc/**.xlsx' - - '.hpc/**' + - "**.md" + - "**.pdf" + - "**.tex" + - "**.jpg" + - "**.jpeg" + - "**.png" + - "**.bbl" + - "**.bib" + - "doc/**.dat" + - "doc/**.ipynb" + - "doc/**.py" + - "doc/**.sh" + - "doc/**.xlsx" + - ".hpc/**" concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true @@ -45,20 +45,26 @@ jobs: name: Check format runs-on: ubuntu-latest steps: - - - name: Checkout modflow6 + - name: Checkout MF6 uses: actions/checkout@v4 - - uses: prefix-dev/setup-pixi@v0.7.0 + - name: Setup pixi + uses: prefix-dev/setup-pixi@v0.8.1 with: - pixi-version: v0.19.1 + pixi-version: v0.24.2 - name: Check Fortran source formatting run: pixi run check-format - name: Check MSVS project files run: pixi run check-vfproj - + + - name: Check python lint + run: pixi run check-python-lint + + - name: Check python format + run: pixi run check-python-format + - name: Check CITATION.cff uses: dieghernan/cff-validator@v3 @@ -69,31 +75,31 @@ jobs: FC: gfortran FC_V: 13 steps: - - - name: Checkout modflow6 + - name: Checkout MF6 uses: actions/checkout@v4 - + - name: Setup ${{ env.FC }} ${{ env.FC_V }} uses: fortran-lang/setup-fortran@v1 with: compiler: gcc version: ${{ env.FC_V }} - - uses: prefix-dev/setup-pixi@v0.7.0 + - name: Setup pixi + uses: prefix-dev/setup-pixi@v0.8.1 with: - pixi-version: v0.19.1 + pixi-version: v0.24.2 - - name: Meson setup + - name: Setup MF6 run: pixi run setup -Dwerror=true builddir - - name: Meson compile + - name: Build MF6 run: pixi run build builddir - name: Show build log if: failure() run: cat builddir/meson-logs/meson-log.txt - - name: Meson test + - name: Unit test MF6 run: pixi run test builddir smoke_test: @@ -106,11 +112,11 @@ jobs: FC: gfortran FC_V: 13 steps: - - name: Checkout modflow6 + - name: Checkout MF6 uses: actions/checkout@v4 with: path: modflow6 - + - name: Checkout test-drive uses: actions/checkout@v4 with: @@ -124,9 +130,9 @@ jobs: version: ${{ env.FC_V }} - name: Setup pixi - uses: prefix-dev/setup-pixi@v0.7.0 + uses: prefix-dev/setup-pixi@v0.8.1 with: - pixi-version: v0.19.1 + pixi-version: v0.24.2 manifest-path: "modflow6/pixi.toml" - name: Custom pixi install @@ -140,7 +146,7 @@ jobs: pixi run --manifest-path=../modflow6/pixi.toml meson install -C builddir echo "PKG_CONFIG_PATH=$(pwd)/lib/pkgconfig:$PKG_CONFIG_PATH" >> $GITHUB_ENV - - name: Build modflow6 + - name: Build MF6 working-directory: modflow6 run: | pixi run setup builddir @@ -150,8 +156,8 @@ jobs: if: failure() working-directory: modflow6 run: cat builddir/meson-logs/meson-log.txt - - - name: Unit test programs + + - name: Unit test MF6 working-directory: modflow6 run: pixi run test builddir @@ -165,7 +171,7 @@ jobs: GITHUB_TOKEN: ${{ github.token }} run: pixi run get-exes - - name: Test programs + - name: Test MF6 working-directory: modflow6 run: | if [ "${{ github.ref_name }}" == "master" ]; then @@ -182,7 +188,7 @@ jobs: path: modflow6/autotest/.failed test_gfortran: - name: Test gnu fortran + name: Test GNU fortran needs: - lint - build @@ -191,7 +197,25 @@ jobs: strategy: fail-fast: false matrix: - os: [ ubuntu-22.04, macos-12, macos-14, windows-2022 ] + include: + # intel mac, release mode + - os: macos-13 + debug: false + # arm mac, release mode + - os: macos-14 + debug: false + # arm mac, debug mode + - os: macos-14 + debug: true + # ubuntu, release mode + - os: ubuntu-22.04 + debug: false + # ubuntu, debug mode + - os: ubuntu-22.04 + debug: true + # windows, release mode + - os: windows-2022 + debug: false defaults: run: shell: bash @@ -199,23 +223,23 @@ jobs: FC: gfortran FC_V: 13 steps: - - name: Checkout modflow6 + - name: Checkout MF6 uses: actions/checkout@v4 with: path: modflow6 - - name: Checkout modflow6-testmodels + - name: Checkout test models uses: actions/checkout@v4 with: repository: MODFLOW-USGS/modflow6-testmodels path: modflow6-testmodels - - - name: Checkout modflow6-examples + + - name: Checkout examples uses: actions/checkout@v4 with: repository: MODFLOW-USGS/modflow6-examples path: modflow6-examples - + - name: Setup ${{ env.FC }} ${{ env.FC_V }} uses: fortran-lang/setup-fortran@v1 with: @@ -223,9 +247,9 @@ jobs: version: ${{ env.FC_V }} - name: Setup pixi - uses: prefix-dev/setup-pixi@v0.7.0 + uses: prefix-dev/setup-pixi@v0.8.1 with: - pixi-version: v0.19.1 + pixi-version: v0.24.2 manifest-path: "modflow6/pixi.toml" - name: Custom pixi install @@ -233,7 +257,7 @@ jobs: run: pixi run install - name: Set LDFLAGS (macOS) - if: matrix.os == 'macos-14' + if: runner.os == 'macOS' run: | os_ver=$(sw_vers -productVersion | cut -d'.' -f1) if (( "$os_ver" > 12 )); then @@ -241,11 +265,13 @@ jobs: echo "LDFLAGS=$ldflags" >> $GITHUB_ENV fi - - name: Build modflow6 + - name: Build MF6 working-directory: modflow6 run: | setupargs="" - if [[ "${{ matrix.os }}" == "macos-14" ]]; then + if [[ "${{ matrix.debug }}" == "true" ]]; then + setupargs="-Ddebug=true -Doptimization=0" + elif [[ "${{ matrix.os }}" == "macos-14" ]]; then setupargs="-Doptimization=1" fi pixi run setup builddir $setupargs @@ -255,8 +281,8 @@ jobs: if: failure() working-directory: modflow6 run: cat builddir/meson-logs/meson-log.txt - - - name: Unit test programs + + - name: Unit test MF6 working-directory: modflow6 run: pixi run test builddir @@ -270,7 +296,7 @@ jobs: GITHUB_TOKEN: ${{ github.token }} run: pixi run get-exes - - name: Test modflow6 + - name: Test MF6 working-directory: modflow6 env: REPOS_PATH: ${{ github.workspace }} @@ -289,14 +315,25 @@ jobs: fi pixi run autotest -m "$markers" -k "$filters" - + + - name: Install executables + uses: modflowpy/install-modflow-action@v1 + + - name: Test examples + working-directory: modflow6 + shell: pixi run bash -e {0} + run: | + cp -R bin/* ~/.local/bin/modflow/ + cd ../modflow6-examples/autotest + pytest -v -n auto test_scripts.py + - name: Upload failed test output if: failure() uses: actions/upload-artifact@v4 with: name: failed-${{ matrix.os }}-${{ env.FC }}-${{ env.FC_V }} path: modflow6/autotest/.failed - + - name: Checkout usgslatex if: runner.os == 'Linux' uses: actions/checkout@v4 @@ -318,7 +355,7 @@ jobs: if: runner.os == 'Linux' working-directory: usgslatex/usgsLaTeX run: sudo ./install.sh --all-users - + - name: Test distribution scripts working-directory: modflow6 env: @@ -326,7 +363,7 @@ jobs: run: pixi run test-dist-scripts test_intel_fortran: - name: Test intel fortran + name: Test Intel fortran needs: - lint - build @@ -338,33 +375,44 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-22.04, macos-12, windows-2022] + os: [ubuntu-22.04, macos-13, windows-2022] defaults: run: shell: bash steps: - - - name: Checkout modflow6 + - name: Free disk space (Ubuntu) + if: runner.os == 'Linux' + uses: jlumbroso/free-disk-space@main + with: + tool-cache: true + android: true + dotnet: true + haskell: true + large-packages: true + docker-images: true + swap-storage: true + + - name: Checkout MF6 uses: actions/checkout@v4 with: path: modflow6 - - name: Checkout modflow6-testmodels + - name: Checkout test models uses: actions/checkout@v4 with: repository: MODFLOW-USGS/modflow6-testmodels path: modflow6-testmodels - - - name: Checkout modflow6-examples + + - name: Checkout examples uses: actions/checkout@v4 with: repository: MODFLOW-USGS/modflow6-examples path: modflow6-examples - name: Setup pixi - uses: prefix-dev/setup-pixi@v0.7.0 + uses: prefix-dev/setup-pixi@v0.8.1 with: - pixi-version: v0.19.1 + pixi-version: v0.24.2 manifest-path: "modflow6/pixi.toml" - name: Custom pixi install @@ -381,7 +429,7 @@ jobs: working-directory: modflow6 run: pixi run update-version - - name: Build modflow6 + - name: Build MF6 working-directory: modflow6 run: | pixi run setup builddir @@ -392,7 +440,7 @@ jobs: working-directory: modflow6 run: cat builddir/meson-logs/meson-log.txt - - name: Unit test programs + - name: Unit test MF6 working-directory: modflow6 run: pixi run test builddir @@ -406,7 +454,7 @@ jobs: GITHUB_TOKEN: ${{ github.token }} run: pixi run get-exes - - name: Test programs + - name: Test MF6 working-directory: modflow6 env: REPOS_PATH: ${{ github.workspace }} @@ -416,7 +464,20 @@ jobs: else pixi run autotest -m "not large" fi - + + - name: Install executables + if: runner.os == 'Linux' + uses: modflowpy/install-modflow-action@v1 + + - name: Test examples + if: runner.os == 'Linux' + working-directory: modflow6 + shell: pixi run bash -e {0} + run: | + cp -R bin/* ~/.local/bin/modflow/ + cd ../modflow6-examples/autotest + pytest -v -n auto test_scripts.py + - name: Upload failed test output if: failure() uses: actions/upload-artifact@v4 @@ -429,9 +490,9 @@ jobs: env: GITHUB_TOKEN: ${{ github.token }} run: pixi run test-dist-scripts - - parallel_test: - name: Parallel testing + + extended_test: + name: Extended testing needs: - lint - build @@ -440,35 +501,47 @@ jobs: strategy: fail-fast: false matrix: - os: [ ubuntu-22.04, macos-12, windows-2022 ] + os: [ubuntu-22.04, macos-13, windows-2022] defaults: run: shell: bash - - steps: - - name: Checkout modflow6 + steps: + - name: Checkout MF6 uses: actions/checkout@v4 with: path: modflow6 - name: Setup pixi - uses: prefix-dev/setup-pixi@v0.7.0 + uses: prefix-dev/setup-pixi@v0.8.1 with: - pixi-version: v0.19.1 + pixi-version: v0.24.2 manifest-path: "modflow6/pixi.toml" - name: Custom pixi install working-directory: modflow6 run: pixi run install - - name: Test parallel MF6 + - name: Install additional netcdf testing packages + working-directory: modflow6 + run: pixi run pip install xugrid xarray netcdf4 + + - name: Set LDFLAGS (macOS) + if: matrix.os == 'macos-13' + run: | + os_ver=$(sw_vers -productVersion | cut -d'.' -f1) + if (( "$os_ver" > 12 )); then + ldflags="$LDFLAGS -Wl,-ld_classic" + echo "LDFLAGS=$ldflags" >> $GITHUB_ENV + fi + + - name: Test extended MF6 if: runner.os != 'Windows' - uses: ./modflow6/.github/actions/test-par + uses: ./modflow6/.github/actions/test-extended - - name: Test parallel MF6 (Windows) + - name: Test extended MF6 if: runner.os == 'Windows' - uses: ./modflow6/.github/actions/test-par-win + uses: ./modflow6/.github/actions/test-extended-win - name: Upload failed test output if: failure() diff --git a/.github/workflows/compilers.yml b/.github/workflows/compilers.yml index 0cad55f07aa..e76638851c6 100644 --- a/.github/workflows/compilers.yml +++ b/.github/workflows/compilers.yml @@ -15,30 +15,19 @@ jobs: # combinations from https://github.com/fortran-lang/setup-fortran#runner-compatibility include: # gfortran - - {os: ubuntu-20.04, compiler: gcc, version: 11} - {os: ubuntu-22.04, compiler: gcc, version: 11} - {os: ubuntu-22.04, compiler: gcc, version: 12} - {os: ubuntu-22.04, compiler: gcc, version: 13} - - {os: macos-11, compiler: gcc, version: 11} - - {os: macos-11, compiler: gcc, version: 12} - - {os: macos-11, compiler: gcc, version: 13} - - {os: macos-12, compiler: gcc, version: 11} - - {os: macos-12, compiler: gcc, version: 12} - - {os: macos-12, compiler: gcc, version: 13} - - {os: windows-2019, compiler: gcc, version: 11} - - {os: windows-2019, compiler: gcc, version: 12} - - {os: windows-2019, compiler: gcc, version: 13} + - {os: macos-13, compiler: gcc, version: 11} + - {os: macos-13, compiler: gcc, version: 12} + - {os: macos-13, compiler: gcc, version: 13} + - {os: macos-14, compiler: gcc, version: 11} + - {os: macos-14, compiler: gcc, version: 12} + - {os: macos-14, compiler: gcc, version: 13} - {os: windows-2022, compiler: gcc, version: 11} - {os: windows-2022, compiler: gcc, version: 12} - {os: windows-2022, compiler: gcc, version: 13} # ifx - - {os: ubuntu-20.04, compiler: intel, version: 2024.1} - - {os: ubuntu-20.04, compiler: intel, version: "2024.0"} - - {os: ubuntu-20.04, compiler: intel, version: 2023.2} - - {os: ubuntu-20.04, compiler: intel, version: 2023.1} - - {os: ubuntu-20.04, compiler: intel, version: "2023.0"} - - {os: ubuntu-20.04, compiler: intel, version: 2022.2.1} - - {os: ubuntu-20.04, compiler: intel, version: 2022.2} - {os: ubuntu-22.04, compiler: intel, version: 2024.1} - {os: ubuntu-22.04, compiler: intel, version: "2024.0"} - {os: ubuntu-22.04, compiler: intel, version: 2023.2} @@ -46,13 +35,6 @@ jobs: - {os: ubuntu-22.04, compiler: intel, version: "2023.0"} - {os: ubuntu-22.04, compiler: intel, version: 2022.2.1} - {os: ubuntu-22.04, compiler: intel, version: 2022.2} - # no ifx on mac - - {os: windows-2019, compiler: intel, version: 2024.1} - - {os: windows-2019, compiler: intel, version: "2024.0"} - - {os: windows-2019, compiler: intel, version: 2023.2} - - {os: windows-2019, compiler: intel, version: 2023.1} - - {os: windows-2019, compiler: intel, version: "2023.0"} - - {os: windows-2019, compiler: intel, version: 2022.2} - {os: windows-2022, compiler: intel, version: 2024.1} - {os: windows-2022, compiler: intel, version: "2024.0"} - {os: windows-2022, compiler: intel, version: 2023.2} @@ -60,16 +42,6 @@ jobs: - {os: windows-2022, compiler: intel, version: "2023.0"} - {os: windows-2022, compiler: intel, version: 2022.2} # ifort - - {os: ubuntu-20.04, compiler: intel-classic, version: "2021.10"} - - {os: ubuntu-20.04, compiler: intel-classic, version: 2021.9} - - {os: ubuntu-20.04, compiler: intel-classic, version: 2021.8} - - {os: ubuntu-20.04, compiler: intel-classic, version: 2021.7} - - {os: ubuntu-20.04, compiler: intel-classic, version: 2021.6} - - {os: ubuntu-20.04, compiler: intel-classic, version: 2021.5} - - {os: ubuntu-20.04, compiler: intel-classic, version: 2021.4} - - {os: ubuntu-20.04, compiler: intel-classic, version: 2021.3} - - {os: ubuntu-20.04, compiler: intel-classic, version: 2021.2} - - {os: ubuntu-20.04, compiler: intel-classic, version: 2021.1} - {os: ubuntu-22.04, compiler: intel-classic, version: "2021.10"} - {os: ubuntu-22.04, compiler: intel-classic, version: 2021.9} - {os: ubuntu-22.04, compiler: intel-classic, version: 2021.8} @@ -80,31 +52,16 @@ jobs: - {os: ubuntu-22.04, compiler: intel-classic, version: 2021.3} - {os: ubuntu-22.04, compiler: intel-classic, version: 2021.2} - {os: ubuntu-22.04, compiler: intel-classic, version: 2021.1} - - {os: macos-11, compiler: intel-classic, version: "2021.10"} - - {os: macos-11, compiler: intel-classic, version: 2021.9} - - {os: macos-11, compiler: intel-classic, version: 2021.8} - - {os: macos-11, compiler: intel-classic, version: 2021.7} - - {os: macos-11, compiler: intel-classic, version: 2021.6} - - {os: macos-11, compiler: intel-classic, version: 2021.5} - - {os: macos-11, compiler: intel-classic, version: 2021.4} - - {os: macos-11, compiler: intel-classic, version: 2021.3} - - {os: macos-11, compiler: intel-classic, version: 2021.2} - - {os: macos-11, compiler: intel-classic, version: 2021.1} - - {os: macos-12, compiler: intel-classic, version: "2021.10"} - - {os: macos-12, compiler: intel-classic, version: 2021.9} - - {os: macos-12, compiler: intel-classic, version: 2021.8} - - {os: macos-12, compiler: intel-classic, version: 2021.7} - - {os: macos-12, compiler: intel-classic, version: 2021.6} - - {os: macos-12, compiler: intel-classic, version: 2021.5} - - {os: macos-12, compiler: intel-classic, version: 2021.4} - - {os: macos-12, compiler: intel-classic, version: 2021.3} - - {os: macos-12, compiler: intel-classic, version: 2021.2} - - {os: macos-12, compiler: intel-classic, version: 2021.1} - - {os: windows-2019, compiler: intel-classic, version: "2021.10"} - - {os: windows-2019, compiler: intel-classic, version: 2021.9} - - {os: windows-2019, compiler: intel-classic, version: 2021.8} - - {os: windows-2019, compiler: intel-classic, version: 2021.7} - - {os: windows-2019, compiler: intel-classic, version: 2021.6} + - {os: macos-13, compiler: intel-classic, version: "2021.10"} + - {os: macos-13, compiler: intel-classic, version: 2021.9} + - {os: macos-13, compiler: intel-classic, version: 2021.8} + - {os: macos-13, compiler: intel-classic, version: 2021.7} + - {os: macos-13, compiler: intel-classic, version: 2021.6} + - {os: macos-13, compiler: intel-classic, version: 2021.5} + - {os: macos-13, compiler: intel-classic, version: 2021.4} + - {os: macos-13, compiler: intel-classic, version: 2021.3} + - {os: macos-13, compiler: intel-classic, version: 2021.2} + - {os: macos-13, compiler: intel-classic, version: 2021.1} - {os: windows-2022, compiler: intel-classic, version: "2021.10"} - {os: windows-2022, compiler: intel-classic, version: 2021.9} - {os: windows-2022, compiler: intel-classic, version: 2021.8} @@ -138,9 +95,9 @@ jobs: version: ${{ matrix.version }} - name: Setup pixi - uses: prefix-dev/setup-pixi@v0.7.0 + uses: prefix-dev/setup-pixi@v0.8.1 with: - pixi-version: v0.19.1 + pixi-version: v0.24.2 manifest-path: "modflow6/pixi.toml" - name: Custom pixi install diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index d700b05ca30..a86333bea7a 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -14,6 +14,9 @@ on: - '.hpc/**' env: PIXI_BETA_WARNING_OFF: true +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: lint: name: Check format @@ -23,9 +26,9 @@ jobs: - name: Checkout modflow6 uses: actions/checkout@v4 - - uses: prefix-dev/setup-pixi@v0.7.0 + - uses: prefix-dev/setup-pixi@v0.8.1 with: - pixi-version: v0.19.1 + pixi-version: v0.24.2 - name: Check spelling run: pixi run check-spelling @@ -60,19 +63,15 @@ jobs: path: usgslatex - name: Setup pixi - uses: prefix-dev/setup-pixi@v0.7.0 + uses: prefix-dev/setup-pixi@v0.8.1 with: - pixi-version: v0.19.1 + pixi-version: v0.24.2 manifest-path: "modflow6/pixi.toml" - name: Custom pixi install working-directory: modflow6 run: pixi run install - - name: Install additional packages for Sphinx using pip - working-directory: modflow6/.build_rtd_docs - run: pixi run pip install -r requirements.rtd.txt - - name: Print python package versions working-directory: modflow6 run: pixi run pip list @@ -80,15 +79,19 @@ jobs: - name: Install TeX Live run: | sudo apt-get update - sudo apt install texlive-latex-extra texlive-science texlive-font-utils + sudo apt install texlive-science \ + texlive-latex-extra \ + texlive-font-utils \ + texlive-fonts-recommended \ + texlive-fonts-extra - name: Install USGS LaTeX style files and Univers font working-directory: usgslatex/usgsLaTeX run: sudo ./install.sh --all-users - - name: Test building files from dfn's for LaTeX - working-directory: modflow6/distribution - run: pixi run pytest -v build_docs.py::test_build_mf6io_tex_from_dfn + - name: Build MF6IO files from DFNs + working-directory: modflow6 + run: pixi run run-mf6ivar - name: Setup ${{ env.FC }} ${{ env.FC_V }} uses: fortran-lang/setup-fortran@v1 @@ -165,18 +168,35 @@ jobs: working-directory: modflow6 run: pixi run sphinx - - name: Upload results + - name: Upload RTD files uses: actions/upload-artifact@v3 with: name: rtd-files-for-${{ github.sha }} path: | + modflow6/.build_rtd_docs/dev.rst modflow6/.build_rtd_docs/index.rst modflow6/.build_rtd_docs/mf6io.rst - # run-time-comparison is moved to _mf6run by conf.py - modflow6/.build_rtd_docs/_mf6run/ + modflow6/.build_rtd_docs/_dev/ modflow6/.build_rtd_docs/_mf6io/ + modflow6/.build_rtd_docs/_mf6run/ modflow6/.build_rtd_docs/_static/ + - name: Build PDF documents + working-directory: modflow6 + run: pixi run build-docs + + - name: Upload PDF documents + uses: actions/upload-artifact@v3 + with: + name: mf6io.pdf + path: | + modflow6/mf6io.pdf + modflow6/ReleaseNotes.pdf + modflow6/zonebudget.pdf + modflow6/converter_mf5to6.pdf + modflow6/mf6suptechinfo.pdf + modflow6/mf6examples.pdf + rtd_trigger: name: rtd-trigger needs: rtd_build @@ -215,9 +235,9 @@ jobs: sudo apt-get install doxygen graphviz - name: Setup pixi - uses: prefix-dev/setup-pixi@v0.7.0 + uses: prefix-dev/setup-pixi@v0.8.1 with: - pixi-version: v0.19.1 + pixi-version: v0.24.2 - name: Custom pixi install run: pixi run install diff --git a/.github/workflows/large.yml b/.github/workflows/large.yml index 5e009cf063a..5b45a88481e 100644 --- a/.github/workflows/large.yml +++ b/.github/workflows/large.yml @@ -67,9 +67,9 @@ jobs: path: modflow6-largetestmodels - name: Setup pixi - uses: prefix-dev/setup-pixi@v0.7.0 + uses: prefix-dev/setup-pixi@v0.8.1 with: - pixi-version: v0.19.1 + pixi-version: v0.24.2 manifest-path: "modflow6/pixi.toml" - name: Custom pixi install diff --git a/.github/workflows/pixi_auto_update.yml b/.github/workflows/pixi_auto_update.yml index 1df768e0af0..56d1bda8a01 100644 --- a/.github/workflows/pixi_auto_update.yml +++ b/.github/workflows/pixi_auto_update.yml @@ -12,20 +12,24 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: prefix-dev/setup-pixi@v0.7.0 + - uses: prefix-dev/setup-pixi@v0.8.1 with: - pixi-version: v0.19.1 + pixi-version: v0.24.2 cache: false - name: Update pixi lock file run: | rm pixi.lock - pixi install - - uses: peter-evans/create-pull-request@v6 + pixi global install pixi-diff-to-markdown + printf "Update pixi dependencies to the latest version\n\n" >> diff.md + pixi update --json | pixi exec pixi-diff-to-markdown >> diff.md + + - uses: peter-evans/create-pull-request@v7 with: token: ${{ secrets.GITHUB_TOKEN }} branch: update/pixi-lock title: Update pixi lock file commit-message: "Update `pixi.lock`" - body: Update pixi dependencies to the latest version. + body-path: diff.md + add-paths: pixi.lock author: "GitHub " diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 15c48b538c3..2b4e86acb04 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -37,7 +37,7 @@ on: description: 'Linux runner image to build binaries on.' required: false type: string - default: 'ubuntu-20.04' + default: 'ubuntu-22.04' run_tests: description: Run tests after building binaries.' required: false @@ -62,7 +62,7 @@ env: PIXI_BETA_WARNING_OFF: true jobs: build: - name: Build binaries (${{ matrix.os }}, parallel=${{ matrix.parallel }}) + name: Build binaries (${{ matrix.os }}, extended=${{ matrix.extended }}) runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -72,27 +72,27 @@ jobs: compiler: ${{ inputs.compiler_toolchain }} version: ${{ inputs.compiler_version }} optimization: 2 - parallel: false + extended: false - os: macos-13 compiler: ${{ inputs.compiler_toolchain }} version: ${{ inputs.compiler_version }} optimization: 2 - parallel: false + extended: false - os: macos-14 compiler: gcc version: 13 optimization: 1 - parallel: false + extended: false - os: windows-2022 compiler: ${{ inputs.compiler_toolchain }} version: ${{ inputs.compiler_version }} optimization: 2 - parallel: false + extended: false - os: windows-2022 compiler: intel-classic version: "2021.7" optimization: 2 - parallel: true + extended: true defaults: run: shell: bash -l {0} @@ -108,15 +108,19 @@ jobs: ref: ${{ inputs.branch }} - name: Setup pixi - uses: prefix-dev/setup-pixi@v0.7.0 + uses: prefix-dev/setup-pixi@v0.8.1 with: - pixi-version: v0.19.1 + pixi-version: v0.24.2 manifest-path: "modflow6/pixi.toml" - name: Custom pixi install working-directory: modflow6 run: pixi run install + - name: Install additional netcdf testing packages + working-directory: modflow6 + run: pixi run pip install xugrid xarray netcdf4 + - name: Setup Micromamba uses: mamba-org/setup-micromamba@v1 with: @@ -128,7 +132,7 @@ jobs: powershell - name: Setup ${{ matrix.compiler }} ${{ matrix.version }} - if: (!(runner.os == 'Windows' && matrix.parallel)) + if: (!(runner.os == 'Windows' && matrix.extended)) id: setup-fortran uses: fortran-lang/setup-fortran@v1 with: @@ -165,8 +169,8 @@ jobs: id: ostag run: | ostag=$(python -c "from modflow_devtools.ostags import get_ostag; print(get_ostag())") - if [[ "${{ matrix.parallel }}" == "true" ]]; then - ostag="${ostag}par" + if [[ "${{ matrix.extended }}" == "true" ]]; then + ostag="${ostag}ext" fi echo "ostag=$ostag" >> $GITHUB_OUTPUT @@ -189,7 +193,7 @@ jobs: fi - name: Build binaries - if: (!(runner.os == 'Windows' && matrix.parallel)) + if: (!(runner.os == 'Windows' && matrix.extended)) working-directory: modflow6 run: | meson setup builddir --prefix=$(pwd) --libdir=bin -Doptimization=${{ matrix.optimization }} @@ -204,21 +208,21 @@ jobs: lipo -info mf6 - name: Build binaries (Windows) - if: runner.os == 'Windows' && matrix.parallel && !inputs.run_tests - uses: ./modflow6/.github/actions/build-par-win + if: runner.os == 'Windows' && matrix.extended && !inputs.run_tests + uses: ./modflow6/.github/actions/build-extended-win - name: Build and test binaries (Windows) - if: runner.os == 'Windows' && matrix.parallel && inputs.run_tests && inputs.developmode - uses: ./modflow6/.github/actions/test-par-win + if: runner.os == 'Windows' && matrix.extended && inputs.run_tests && inputs.developmode + uses: ./modflow6/.github/actions/test-extended-win - name: Build and test binaries (Windows) - if: runner.os == 'Windows' && matrix.parallel && inputs.run_tests && !inputs.developmode - uses: ./modflow6/.github/actions/test-par-win + if: runner.os == 'Windows' && matrix.extended && inputs.run_tests && !inputs.developmode + uses: ./modflow6/.github/actions/test-extended-win env: MARKERS: not developmode - name: Copy deps to bin dir - if: runner.os == 'Windows' && matrix.parallel + if: runner.os == 'Windows' && matrix.extended working-directory: modflow6/bin shell: cmd run: | @@ -244,6 +248,12 @@ jobs: copy "C:\Program Files (x86)\Intel\oneAPI\mpi\latest\bin\hydra_pmi_proxy.exe" . copy "C:\Program Files (x86)\Intel\oneAPI\mpi\latest\bin\hydra_service.exe" . copy "%GITHUB_WORKSPACE%\petsc\arch-mswin-c-opt\lib\libpetsc.dll" . + copy "%GITHUB_WORKSPACE%\netcdf\netCDF4.9.2-NC4-64\bin\hdf5.dll" . + copy "%GITHUB_WORKSPACE%\netcdf\netCDF4.9.2-NC4-64\bin\hdf5_hl.dll" . + copy "%GITHUB_WORKSPACE%\netcdf\netCDF4.9.2-NC4-64\bin\libcurl.dll" . + copy "%GITHUB_WORKSPACE%\netcdf\netCDF4.9.2-NC4-64\bin\netcdf.dll" . + copy "%GITHUB_WORKSPACE%\netcdf\netCDF4.9.2-NC4-64\bin\zlib1.dll" . + copy "%GITHUB_WORKSPACE%\netcdf\netcdf-fortran-4.6.1\build\fortran\netcdff.dll" . :: remove rebuilt and downloaded dirs if exist rebuilt rd /s /q rebuilt @@ -459,6 +469,10 @@ jobs: name: deprecations path: modflow6/doc/mf6io/mf6ivar/md/deprecations.md + - name: Build MF6IO files from DFNs + working-directory: modflow6/doc/mf6io/mf6ivar + run: python mf6ivar.py + - name: Build documentation env: # this step is lazy about building the mf6 examples PDF document, first @@ -498,9 +512,9 @@ jobs: - os: macos-13 - os: macos-14 - os: windows-2022 - parallel: false + extended: false - os: windows-2022 - parallel: true + extended: true defaults: run: shell: bash -l {0} @@ -552,8 +566,8 @@ jobs: id: ostag run: | ostag=$(python -c "from modflow_devtools.ostags import get_ostag; print(get_ostag())") - if [[ "${{ matrix.parallel }}" == "true" ]]; then - ostag="${ostag}par" + if [[ "${{ matrix.extended }}" == "true" ]]; then + ostag="${ostag}ext" fi echo "ostag=$ostag" >> $GITHUB_OUTPUT @@ -703,4 +717,4 @@ jobs: if [[ "${{ inputs.full }}" == "true" ]]; then cmd="$cmd --full" fi - eval "$cmd" \ No newline at end of file + eval "$cmd" diff --git a/.github/workflows/release_dispatch.yml b/.github/workflows/release_dispatch.yml index 1feab0f6526..edc979176ae 100644 --- a/.github/workflows/release_dispatch.yml +++ b/.github/workflows/release_dispatch.yml @@ -252,7 +252,7 @@ jobs: cache-environment: true - name: Download artifacts - uses: dawidd6/action-download-artifact@v3 + uses: dawidd6/action-download-artifact@v7 - name: Draft release working-directory: modflow6 diff --git a/.gitignore b/.gitignore index a45b2864baa..b00c130eca4 100644 --- a/.gitignore +++ b/.gitignore @@ -70,10 +70,6 @@ bin/** UserPrefs.xml tmp_simulations/ -autotest/temp/ -autotest/tempbin/ -autotest/*.html -autotest/notebooks/ distribution/temp/ distribution/temp_zip/ @@ -117,11 +113,15 @@ CMakeFiles/ .build_rtd_docs/_mf6io .build_rtd_docs/_mf6src .build_rtd_docs/_mf6run +.build_rtd_docs/_dev latex/ html/ xml/ distribution/run-time-comparison.md doc/ReleaseNotes/run-time-comparison.tex +doc/ReleaseNotes/deprecations.tex +doc/mf6io/mf6ivar/md +doc/mf6io/mf6ivar/tex # Intel Fortran Visual Studio intermediate files msvs/*.fdz @@ -135,6 +135,11 @@ modflow6.code-workspace # unittests unittests/ autotest/.failed +autotest/.temp/ +autotest/temp/ +autotest/tempbin/ +autotest/*.html +autotest/notebooks/ **/__pycache__ **/.benchmarks diff --git a/.hpc/cray-hovenweep-meson-build.slurm.batch b/.hpc/cray-hovenweep-meson-build.slurm.batch index 56ca5d7645a..84d7de2951a 100644 --- a/.hpc/cray-hovenweep-meson-build.slurm.batch +++ b/.hpc/cray-hovenweep-meson-build.slurm.batch @@ -12,8 +12,9 @@ set -euxo pipefail # load appropriate modules module switch PrgEnv-${PE_ENV,,} PrgEnv-intel -module load petsc/3.15.5 meson/1.2.1 ninja/1.11.1 +module load petsc/3.15.5 cray-netcdf cray-hdf5 meson/1.2.1 ninja/1.11.1 export PKG_CONFIG_PATH=$CRAY_MPICH_DIR/lib/pkgconfig:$PKG_CONFIG_PATH +export PKG_CONFIG_PATH=$NETCDF_DIR/lib/pkgconfig:$HDF5_DIR/lib/pkgconfig:$PKG_CONFIG_PATH # list loaded modules module list @@ -47,4 +48,4 @@ cd $TESTDIR $BINDIR/mf6 # parallel run -srun $BINDIR/mf6 -p \ No newline at end of file +srun $BINDIR/mf6 -p diff --git a/.hpc/cray-meson-build.slurm.batch b/.hpc/cray-meson-build.slurm.batch index d6633b078b5..b9162b2a327 100644 --- a/.hpc/cray-meson-build.slurm.batch +++ b/.hpc/cray-meson-build.slurm.batch @@ -12,8 +12,9 @@ set -euxo pipefail # load appropriate modules module switch PrgEnv-${PE_ENV,,} PrgEnv-intel -module load cray-petsc meson ninja -export PKG_CONFIG_PATH=/opt/cray/pe/mpt/7.7.19/gni/mpich-intel/16.0/lib/pkgconfig:/opt/cray/pe/petsc/3.14.5.0/real/INTEL/19.1/x86_skylake/lib/pkgconfig:$PKG_CONFIG_PATH +module load cray-petsc cray-netcdf cray-hdf5 meson ninja +export PKG_CONFIG_PATH=$CRAY_MPICH_DIR/lib/pkgconfig:$PETSC_DIR/lib/pkgconfig:$PKG_CONFIG_PATH +export PKG_CONFIG_PATH=$NETCDF_DIR/lib/pkgconfig:$HDF5_DIR/lib/pkgconfig:$PKG_CONFIG_PATH # list loaded modules module list @@ -47,4 +48,4 @@ cd $TESTDIR $BINDIR/mf6 # parallel run -srun $BINDIR/mf6 -p \ No newline at end of file +srun $BINDIR/mf6 -p diff --git a/.hpc/sstat_poll.py b/.hpc/sstat_poll.py index 12e60f101a0..157c8c44048 100644 --- a/.hpc/sstat_poll.py +++ b/.hpc/sstat_poll.py @@ -1,6 +1,5 @@ import argparse import pathlib as pl -import sys import time from subprocess import PIPE, STDOUT, Popen @@ -68,10 +67,7 @@ def _run_command( + "by specifying the format argument " + "(--format=JobID,AveCPU,AveRSS,MaxRSS,...)." ) - parser = argparse.ArgumentParser( - "sstat_poll", - description=description, - ) + parser = argparse.ArgumentParser("sstat_poll", description=description) parser.add_argument("jobid", help="SLURM JobID", type=int) parser.add_argument( "--format", @@ -110,9 +106,6 @@ def _run_command( ) slurm_args = parser.parse_args() - if sys.version_info < (3, 8): - sys.exit("Python version must be 3.8 or higher.") - print(f"SLURM command: {slurm_args.command}") print(f"JobID: {slurm_args.jobid}") @@ -141,9 +134,7 @@ def _run_command( ) is None ): - raise ValueError( - f"SLURM command '{slurm_args.command}' does not exist" - ) + raise ValueError(f"SLURM command '{slurm_args.command}' does not exist") end_tag = f"sstat:,error:,no,steps,running,for,job,{slurm_args.jobid}" # open file diff --git a/.vscode/README.md b/.vscode/README.md index 962fe1d07b2..586b9021c1b 100644 --- a/.vscode/README.md +++ b/.vscode/README.md @@ -1,100 +1,129 @@ -# Compiling and Visual Debugging with VSCode +# Using VSCode with MODFLOW 6 -VSCode is a free integrated development environment for Windows, Linux, and -MacOS. There are two major advantages over Visual Studio: +This document describes how to use VSCode to modify, format, build and test MODFLOW 6. VSCode is a free integrated development environment for Windows, Linux, and MacOS. Most of VSCode's source code is open-source and the releases are (proprietary) freeware. -* Most of VSCode's source code is open-source and the releases are (proprietary) freeware. -* VSCode runs on Linux. +The folder containing this README markdown file (`.vscode/`) contains the configuration files for using VSCode for MODFLOW 6 development. At the moment they are used for formatting, building, and debugging MODFLOW 6. In order to build MODFLOW 6 follow the steps in [DEVELOPER.md](../DEVELOPER.md) -This folder contains the configuration files for using VSCode for MODFLOW 6 -development. -At the moment they are used for building and debugging MODFLOW 6. -In order to build MODFLOW 6 follow the steps in [DEVELOPER.md](../DEVELOPER.md) + + -## Visual Studio Code +- [Setting up Visual Studio Code](#setting-up-visual-studio-code) + - [Installation](#installation) + - [Visual Studio Code Extensions](#visual-studio-code-extensions) + - [Dependencies](#dependencies) + - [Running VSCode](#running-vscode) + - [Final VSCode setup](#final-vscode-setup) +- [MODFLOW 6 VSCode Tasks](#modflow-6-vscode-tasks) + - [Compiling](#compiling) + - [Debugging](#debugging) + - [Formatting](#formatting) + - [Additional tasks](#additional-tasks) + + + +## Setting up Visual Studio Code + +### Installation Install VSCode from https://code.visualstudio.com/ -### Extensions +### Visual Studio Code Extensions Install the following VSCode extensions: - Modern Fortran: https://marketplace.visualstudio.com/items?itemName=krvajalm.linter-gfortran -Note: The Remote - WSL extension may be required if you want to use a windows VSCode -installation in a WSL environment. +Note: The [Remote - WSL extension](https://code.visualstudio.com/docs/remote/wsl) may be required if you want to use a windows VSCode installation in a WSL environment. ### Dependencies -Required and optional dependencies for MODFLOW 6 are discussed in [DEVELOPER.md](../DEVELOPER.md) +Required and optional dependencies for MODFLOW 6 are discussed in [DEVELOPER.md](../DEVELOPER.md). Required dependencies should be installed prior to setting up VSCode for MODFLOW 6. -### Settings - -Add [settings.json](https://code.visualstudio.com/docs/getstarted/settings#_settingsjson) to the -`modflow6/.vscode` directory if not already there. The following settings can be considered a -starting place as the contents of this file are dictated both by desired VSCode behavior and -environmental factors: +### Running VSCode -In general, to determine the path of an installed tool in your environment run: -- bash: `which `, e.g. `which fortls` -- cmd: `where `, e.g. `where python` -- PowerShell: `Get-Command ` e.g. `Get-Command fprettify` +Open the top level `modflow6` repository directory on your system when starting VSCode. The program will then look for the `modflow6/.vscode` directory to discover settings relevant to your session. -1. Activate the conda environment: +A nice alternative on any system is to start VSCode from the shell. For example, in a bash or git bash shell (windows), change to the `modflow6` directory and execute the command: ```bash -conda activate modflow6 +code . ``` -2. Determine the path of `fortls` and `fprettify` +Note the dot (".") at the end of the command. Starting in this way, VSCode will open as desired, inheriting and discovering expected runtime settings in the correct directory location. -3. Set the setting "fortran.fortls.path" and "fortran.formatting.path": -```json -{ - "fortran.fortls.path": "/path/to/fortls", - "fortran.formatting.path": "/path/to/fprettify", -} -``` +### Final VSCode setup -The fortran formatter can be integrated with VSCode using the following settings: +A few additional steps are required to finalize the VSCode setup for MODFLOW 6. The remaining steps are: -```json -{ - "[fortran]": { - "editor.formatOnSave": true, - }, - "fortran.formatting.formatter": "fprettify", - "fortran.formatting.fprettifyArgs": ["-c", "/path/to/modflow6/.fprettify.yaml"], -} -``` +1. [Select the python interpreter](https://code.visualstudio.com/docs/python/environments#_working-with-python-interpreters) for the MODFLOW 6 workspace. To select the python interpreter run: -Setting the formatter up in this way will cause a source file to reformat with each explicit save. + * Press `Ctrl + Shift + P` in VSCode. + * Type `Python: Select Interpreter`. + * Select `Run Task` (press Enter). + * Select the `modflow6` conda environment. -### Running VSCode +2. Open a new terminal in VSCode and determine the path to the Fortran language server (`fortls`) and `fprettify` using the syntax for your terminal (`cmd`, `bash`, `powershell`). -Open the top level `modflow6` repository directory on your system when starting VSCode. The program will -then look for the `modflow6/.vscode` directory to discover settings relevant to your session. +3. Set the setting "fortran.fortls.path" and "fortran.formatting.path": -A nice alternative on any system is to start VSCode from the shell. For example, in a bash or git bash -shell (windows), change to the `modflow6` directory and execute the command: + ```json + { + "fortran.fortls.path": "/path/to/fortls", + "fortran.formatting.path": "/path/to/fprettify", + } + ``` + +4. The fortran formatter can be integrated with VSCode using the following settings: + + ```json + { + "[fortran]": { + "editor.formatOnSave": true, + }, + "fortran.formatting.formatter": "fprettify", + "fortran.formatting.fprettifyArgs": ["-c", "/path/to/modflow6/.fprettify.yaml"], + } + ``` + + Setting the formatter up in this way will cause a source file to reformat with each explicit save. + +In general, to determine the path to python, the fortran language server (`fortls`), and `fprettify` in your environment run: + +- bash, zsh: `which `, e.g. `which fortls` +- cmd: `where `, e.g. `where python` +- PowerShell: `Get-Command ` e.g. `Get-Command fprettify` -```bash -code . -``` +## MODFLOW 6 VSCode Tasks -Note the dot. Starting in this way, VSCode will open as desired, inheriting and discovering -expected runtime settings in the correct directory location. +A number of MODFLOW 6 development tasks in the [`.vscode/settings.json`](./settings.json) file in the MODFLOW 6 repository. Debugging tasks are included in the `.vscode/launch.json` file, that you will create (instructions below). The tasks includes tasks to compile, debug, and format files. A number of miscellaneous tasks are also included to help prepare required files for Pull Requests (for example, makefiles). ### Compiling In order to compile Fortran source run: * Press `Ctrl + Shift + P` in VSCode. -* Type `Tasks`. -* Select `Run Task` (press Enter). +* Type `Tasks: Run Build Task` (press Enter). * Select the suitable task for your situation. +Tasks are available to build MODFLOW 6 using gfortran and Intel Fortran (ifort). If you have used one of the Rebuild tasks, Build tasks for the same compiler can be used to just recompile modified source files and relink the object files. There are also pixi tasks for MODFLOW 6 build using gfortran. + +Available compiling tasks include: + +* `Rebuild mf6 (gfortran, release)` +* `Rebuild mf6 (ifort, release)` +* `Rebuild mf6 (gfortran, debug)` +* `Rebuild mf6 (ifort, debug)` +* `Build mf6 (gfortran, release)` +* `Build mf6 (ifort, release)` +* `Build mf6 (gfortran, debug)` +* `Build mf6 (ifort, debug)` +* `Pixi - Rebuild mf6 (gfortran, release)` +* `Pixi - Rebuild mf6 (gfortran, debug)` +* `Pixi - Build mf6 (gfortran, release)` +* `Pixi - Build mf6 (gfortran, debug)` + + ### Debugging Add a `launch.json` in `.vscode` similar to this. @@ -154,3 +183,39 @@ After building modflow, you can start debugging. - Set a breakpoint somewhere in the source code. - Press `Ctrl + F5` to start debugging. + +### Formatting + +There are a number of VSCode tasks to determine if any of the Fortran source files, python code or scripts, LaTeX files, and markdown files in the MODFLOW 6 repository need to be reformatted. + +In order format file run: + +* Press `Ctrl + Shift + P` in VSCode. +* Type `Tasks: Run Build Task` (press Enter). +* Select the suitable task for your situation. + +Currently available formatting tasks include: + +* `Check spelling` - check spelling in Fortran source files, python code or scripts, LaTeX files, and markdown files +* `Check Fortran format` - check the format of Fortran source files using `fprettify` +* `Check python format` - check the python formatting using `ruff` +* `Check python lint` - check python files for programmatic and stylistic errors using `ruff` + +The Fortran format task is only needed if the fortran formatter has not been [integrated with VSCode](#settings). + +### Additional tasks + +A number of additional VSCode tasks are available to perform common tasks that are required before making a Pull Request (see the [Developer documents](../DEVELOPER.md)). + +In order run additional tasks run: + +* Press `Ctrl + Shift + P` in VSCode. +* Type `Tasks: Run Build Task` (press Enter). +* Select the suitable task for your situation. + +Currently available additional tasks include: + +* `Run update_flopy.py` - updates FloPy MODFLOW 6 classes in the modflow6 Conda environment using current MODFLOW 6 definition files. +* `Run dfn2f90.py` - updates Fortran definitions using current MODFLOW 6 definition files. +* `Run mf6ivar.py` - Regenerates LaTeX file for the input output guide current MODFLOW 6 definition files. +* `Rebuild makefiles` - Rebuilds the GNU makefile for MODFLOW 6 (`mf6`), ZONEBUDGET 6 (`zbud6`), and the MODFLOW Converter (`mf5to6`). \ No newline at end of file diff --git a/.vscode/build_vscode.py b/.vscode/build_vscode.py index 208d0fdc538..b690f843adb 100644 --- a/.vscode/build_vscode.py +++ b/.vscode/build_vscode.py @@ -8,16 +8,17 @@ parser = argparse.ArgumentParser() parser.add_argument("--compiler", type=str) parser.add_argument("--buildtype", type=str) +parser.add_argument("--pixi", action="store_true") parser.add_argument("action") args = parser.parse_args() os.environ["FC"] = args.compiler -builddir = f"builddir_{platform.system()}_{args.compiler}_{args.buildtype}" +builddir = f"_builddir_{platform.system()}_{args.compiler}_{args.buildtype}" -arg_parallel = "-Dparallel=false" -if os.getenv("BUILD_PARALLEL_MF6") is not None: - if os.environ["BUILD_PARALLEL_MF6"] == '1': - arg_parallel = "-Dparallel=true" +arg_extended = "-Dextended=false" +if os.getenv("BUILD_EXTENDED_MF6") is not None: + if os.environ["BUILD_EXTENDED_MF6"] == '1': + arg_extended = "-Dextended=true" if args.action == "rebuild" and os.path.isdir(builddir): shutil.rmtree(builddir) @@ -28,15 +29,24 @@ setup_flag = ["-Ddebug=true", "-Doptimization=0"] if not os.path.isdir(builddir): - command = [ - "meson", - "setup", + if args.pixi: + command = [ + "pixi", + "run", + "setup", + ] + else: + command = [ + "meson", + "setup", + ] + command += [ builddir, "--prefix", os.getcwd(), "--libdir", "bin", - arg_parallel, + arg_extended, ] + setup_flag print("Run:", shlex.join(command)) subprocess.run( @@ -52,6 +62,10 @@ if os.path.isfile(path): os.remove(path) -command = ["meson", "install", "-C", builddir] +if args.pixi: + command = ["pixi", "run", "build",] +else: + command = ["meson", "install", "-C"] +command += [builddir] print("Run:", shlex.join(command)) subprocess.run(command, check=True) diff --git a/.vscode/run_python.cmd b/.vscode/run_python.cmd index 87c6f3de58b..a0bc7a2c59d 100644 --- a/.vscode/run_python.cmd +++ b/.vscode/run_python.cmd @@ -7,4 +7,4 @@ if "%3" == "ifort" ( call conda activate modflow6 rem run python script -python %1 %2 %3 %4 %5 %6 +python %1 %2 %3 %4 %5 %6 %7 diff --git a/.vscode/run_python.sh b/.vscode/run_python.sh index cbd3b27fcc9..fd92a20d019 100755 --- a/.vscode/run_python.sh +++ b/.vscode/run_python.sh @@ -9,4 +9,4 @@ eval "$(conda shell.bash hook)" conda activate modflow6 # run python script -python $1 $2 $3 $4 $5 $6 +python $1 $2 $3 $4 $5 $6 $7 diff --git a/.vscode/tasks.json b/.vscode/tasks.json index c8285990d59..fbbc193226b 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -303,5 +303,322 @@ }, "problemMatcher": [] }, + { + "label": "Pixi - Rebuild MF6 (gfortran, release)", + "command": "${workspaceFolder}/.vscode/run_python.sh", + "windows": { + "command": "${workspaceFolder}/.vscode/run_python.cmd", + "args": [ + "${workspaceFolder}/.vscode/build_vscode.py", + "--compiler", + "gfortran", + "--buildtype", + "release", + "--pixi", + "rebuild", + ], + }, + "args": [ + "${workspaceFolder}/.vscode/build_vscode.py", + "--compiler", + "gfortran", + "--buildtype", + "release", + "--pixi", + "rebuild", + ], + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "clear": true + } + }, + { + "label": "Pixi - Build MF6 (gfortran, release)", + "command": "${workspaceFolder}/.vscode/run_python.sh", + "windows": { + "command": "${workspaceFolder}/.vscode/run_python.cmd", + "args": [ + "${workspaceFolder}/.vscode/build_vscode.py", + "--compiler", + "gfortran", + "--buildtype", + "release", + "--pixi", + "build", + ], + "problemMatcher": "$msCompile" + }, + "args": [ + "${workspaceFolder}/.vscode/build_vscode.py", + "--compiler", + "gfortran", + "--buildtype", + "release", + "--pixi", + "build", + ], + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "clear": true + } + }, + { + "label": "Pixi - Build MF6 (gfortran, debug)", + "command": "${workspaceFolder}/.vscode/run_python.sh", + "windows": { + "command": "${workspaceFolder}/.vscode/run_python.cmd", + "args": [ + "${workspaceFolder}/.vscode/build_vscode.py", + "--compiler", + "gfortran", + "--buildtype", + "debug", + "--pixi", + "build", + ], + "problemMatcher": "$msCompile" + }, + "args": [ + "${workspaceFolder}/.vscode/build_vscode.py", + "--compiler", + "gfortran", + "--buildtype", + "debug", + "--pixi", + "build", + ], + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "clear": true + } + }, + { + "label": "Pixi - Rebuild MF6 (gfortran, debug)", + "command": "${workspaceFolder}/.vscode/run_python.sh", + "windows": { + "command": "${workspaceFolder}/.vscode/run_python.cmd", + "args": [ + "${workspaceFolder}/.vscode/build_vscode.py", + "--compiler", + "gfortran", + "--buildtype", + "debug", + "--pixi", + "rebuild", + ], + }, + "args": [ + "${workspaceFolder}/.vscode/build_vscode.py", + "--compiler", + "gfortran", + "--buildtype", + "debug", + "--pixi", + "rebuild", + ], + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "clear": true + } + }, + { + "label": "Pixi - Build MF6 (ifort, release)", + "command": "${workspaceFolder}/.vscode/run_python.sh", + "windows": { + "command": "${workspaceFolder}/.vscode/run_python.cmd", + "args": [ + "${workspaceFolder}/.vscode/build_vscode.py", + "--compiler", + "ifort", + "--buildtype", + "release", + "--pixi", + "build", + ], + "problemMatcher": "$msCompile" + }, + "args": [ + "${workspaceFolder}/.vscode/build_vscode.py", + "--compiler", + "ifort", + "--buildtype", + "release", + "--pixi", + "build", + ], + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "clear": true + } + }, + { + "label": "Pixi - Rebuild MF6 (ifort, release)", + "command": "${workspaceFolder}/.vscode/run_python.sh", + "windows": { + "command": "${workspaceFolder}/.vscode/run_python.cmd", + "args": [ + "${workspaceFolder}/.vscode/build_vscode.py", + "--compiler", + "ifort", + "--buildtype", + "release", + "--pixi", + "rebuild", + ], + }, + "args": [ + "${workspaceFolder}/.vscode/build_vscode.py", + "--compiler", + "ifort", + "--buildtype", + "release", + "--pixi" + "rebuild", + ], + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "clear": true + } + }, + { + "label": "Pixi - Build MF6 (ifort, debug)", + "command": "${workspaceFolder}/.vscode/run_python.sh", + "windows": { + "command": "${workspaceFolder}/.vscode/run_python.cmd", + "args": [ + "${workspaceFolder}/.vscode/build_vscode.py", + "--compiler", + "ifort", + "--buildtype", + "debug", + "--pixi", + "build", + ], + "problemMatcher": "$msCompile" + }, + "args": [ + "${workspaceFolder}/.vscode/build_vscode.py", + "--compiler", + "ifort", + "--buildtype", + "debug", + "--pixi", + "build", + ], + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "clear": true + } + }, + { + "label": "Pixi - Rebuild MF6 (ifort, debug)", + "command": "${workspaceFolder}/.vscode/run_python.sh", + "windows": { + "command": "${workspaceFolder}/.vscode/run_python.cmd", + "args": [ + "${workspaceFolder}/.vscode/build_vscode.py", + "--compiler", + "ifort", + "--buildtype", + "debug", + "--pixi", + "rebuild", + ], + }, + "args": [ + "${workspaceFolder}/.vscode/build_vscode.py", + "--compiler", + "ifort", + "--buildtype", + "debug", + "--pixi", + "rebuild", + ], + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "clear": true + } + }, + { + "label": "Check spelling", + "type": "shell", + "command": "codespell", + "options": {"cwd": "${workspaceFolder}"}, + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "clear": true + }, + "problemMatcher": [] + }, + { + "label": "Check Fortran format", + "type": "shell", + "command": "python .github/common/check_format.py", + "options": {"cwd": "${workspaceFolder}"}, + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "clear": true + }, + "problemMatcher": [] + }, + { + "label": "Check python format", + "type": "shell", + "command": "ruff format --config .github/common/ruff.toml --check .", + "options": {"cwd": "${workspaceFolder}"}, + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "clear": true + }, + "problemMatcher": [] + }, + { + "label": "Check python lint", + "type": "shell", + "command": "ruff check --config .github/common/ruff.toml .", + "options": {"cwd": "${workspaceFolder}"}, + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "clear": true + }, + "problemMatcher": [] + }, + ] } diff --git a/CITATION.cff b/CITATION.cff index af515842683..33414f14ed5 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -2,8 +2,8 @@ cff-version: 1.2.0 message: If you use this software, please cite the software itself. type: software title: MODFLOW 6 Modular Hydrologic Model -version: 6.5.0 -date-released: '2024-05-23' +version: 6.6.0 +date-released: '2024-12-19' doi: 10.5066/F76Q1VQV abstract: MODFLOW 6 is an object-oriented program and framework developed to provide a platform for supporting multiple models and multiple types of models within the diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0126b90c449..c170bf13230 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,172 +1,112 @@ -Contributing -============ +# Contributing to MODFLOW 6 -Contributions to MODFLOW 6 are welcome from the community. As a contributor, here are the guidelines we would like you to follow: +Contributions to MODFLOW 6 are welcome. We ask that contributors follow some guidelines. - - [Code of Conduct](#coc) - - [Question or Problem?](#question) - - [Issues and Bugs](#issue) - - [Feature Requests](#feature) - - [Submission Guidelines](#submit) - - [Coding Rules](#rules) - - [Format Rules](#format) - - [Commit Message Guidelines](#commit) + + -## Code of Conduct -Help us keep MODFLOW 6 open and inclusive. Please read and follow our [Code of Conduct][coc]. +- [Conduct](#conduct) +- [Submissions](#submissions) + - [Bugs](#bugs) + - [Questions](#questions) + - [Requests](#requests) +- [Source code](#source-code) + - [Format](#format) + - [Style guide](#style-guide) +- [Commit messages](#commit-messages) + - [Template](#template) + - [Components](#components) + - [Type](#type) + - [Scope](#scope) + - [Subject](#subject) + - [Body](#body) + - [Footer](#footer) -## Got a Question or Problem? + -Do not open issues for general support questions as we want to keep GitHub issues for bug reports and feature requests. You've got much better chances of getting your question answered on [Stack Overflow](https://stackoverflow.com/questions/tagged/modflow6) where the questions should be tagged with tag `modflow6`. +## Conduct -Stack Overflow is a much better place to ask questions since: +Help us keep MODFLOW 6 open and inclusive. Please read and follow our [Code of Conduct](./CODE_OF_CONDUCT.md). -- there are thousands of people willing to help on Stack Overflow -- questions and answers stay available for public viewing so your question / answer might help someone else -- Stack Overflow's voting system assures that the best answers are prominently visible. +## Submissions -To save your and our time, we will systematically close all issues that are requests for general support and redirect people to Stack Overflow. +### Bugs -## Found a Bug? -If you find a bug in the source code, you can help us by -[submitting an issue](#submit-issue) to our [GitHub Repository][github]. Even better, you can [submit a Pull Request](#submit-pr) with a fix. +If you find a bug, you can help us by submitting an issue. Even better, you can submit a pull request with a fix. -## Missing a Feature? -You can *request* a new feature by [submitting an issue](#submit-issue) to our GitHub Repository. If you would like to *implement* a new feature, please submit an issue with a proposal for your work first, to be sure that we can use it. Please consider what kind of change it is: +Before submitting an issue, please search the issue tracker. Your issue may already have been reported, and the discussion might inform you of workarounds readily available. -* For a **Major Feature**, first open an issue and outline your proposal so that it can be -discussed. This will also allow us to better coordinate our efforts, prevent duplication of work, -and help you to craft the change so that it is successfully accepted into the project. -* **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr). +We want to fix all issues as soon as possible, but we first need to reproduce and confirm them. We ask that all bug reports provide a minimal, complete, and verifiable example of the problem, including the following information: -## Submission Guidelines +- Operating system +- Version of MODFLOW 6 +- A description of the problem contrasting actual with expected behavior +- A minimal recipe to reproduce the problem — e.g. Python/FloPy script or MF6 input files. -### Submitting an Issue +Please provide such an example. This saves maintainers time and ultimately allows us to fix more bugs. While we understand it might be difficult to isolate the essence of a problem, bugs can only be investigated or fixed if problems are accurately identified. Issues lacking sufficient information to reproduce may be closed. -Before you submit an issue, please search the issue tracker, maybe an issue for your problem already exists and the discussion might inform you of workarounds readily available. +File an issue by filling out our [issue form](https://github.com/MODFLOW-USGS/modflow6/issues/new). -We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it. In order to reproduce bugs, we will systematically ask you to provide a minimal, complete, and verifiable example. Having a minimal, complete, and verifiable example gives us a wealth of important information without going back & forth to you with additional questions like: +### Questions -- version of MODFLOW 6 used -- and most importantly - a use-case that fails (ideally an example that uses flopy to generate MODFLOW 6 input files - see test_gwf* python scripts in the `autotest/` directory) +Please do not open issues for general support questions as we want to keep GitHub issues for bug reports and feature requests. Questions can be asked on the [discussions page](https://github.com/MODFLOW-USGS/modflow6/discussions) under the Q&A category or on [Stack Overflow](https://stackoverflow.com/questions/tagged/modflow6) with tag `modflow6`. -We will be insisting on a minimal minimal, complete, and verifiable example in order to save maintainers time and ultimately be able to fix more bugs. We understand that sometimes it might be hard to extract essentials bits of code from a larger code-base but we really need to isolate the problem before we can fix it. +We will systematically close all issues that are requests for general support. -Unfortunately, we are not able to investigate / fix bugs without a minimal, complete, and verifiable example, so if we don't hear back from you we are going to close an issue that doesn't have enough info to be reproduced. +### Requests -You can file new issues by filling out our [new issue form](https://github.com/MODFLOW-USGS/modflow6/issues/new). +You can request a new feature by submitting an issue to our GitHub Repository. +If you would like to implement a new feature: -### Submitting a Pull Request (PR) -Before you submit your Pull Request (PR) consider the following guidelines: +- **Major** features should be discussed first. Please open an issue and outline your proposal. This will also allow us to coordinate our efforts, prevent duplication of work, and help you craft the change so that it can be accepted into the project. +- **Small** features can be submitted directly as a pull request. -1. Search [GitHub](https://github.com/MODFLOW-USGS/modflow6/pulls) for an open or closed PR that relates to your submission. You don't want to duplicate effort. -2. Fork the MODFLOW-USGS/modflow6 repo. -3. Make your changes in a new git branch: +To submit a pull request (PR): - ```shell - git checkout -b my-fix-branch develop - ``` - -4. Create your patch, **including appropriate test cases**. -5. Follow our [Coding Rules](#rules). -6. Run `build_makefiles.py` in the `./distribution/` directory if you have - added any new sourcefiles, removed any source files, or renamed any - source files. -7. Run the full modflow6 test suite, as described in the [developer documentation][dev-doc], - and ensure that all tests pass. -8. Commit your changes using a descriptive commit message that follows our - [commit message conventions](#commit). Adherence to these conventions - is necessary because release notes are automatically generated from these messages. - - ```shell - git commit -a - ``` - Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files. - -9. Push your branch to GitHub: - - ```shell - git push origin my-fix-branch - ``` - -10. In GitHub, send a pull request to `modflow6:develop`. -* If we suggest changes then: - * Make the required updates. - * Re-run the MODFLOW 6 test suites, in the autotest directory, to ensure tests are still passing. The test suites are run using python nosetests and require [flopy](https://github.com/modflowpy/flopy) and [pymake](https://github.com/modflowpy/pymake). - * Rebase your branch and force push to your GitHub repository (this will update your Pull Request): - - ```shell - git rebase develop -i - git push -f - ``` +1. To avoid duplicating effort, [search](https://github.com/MODFLOW-USGS/modflow6/pulls) for an open or closed PR that relates to your submission. +2. Fork the MODFLOW-USGS/modflow6 repo and make your changes in a new branch, following our style and commit message guidelines and [including appropriate test cases](./DEVELOPER.md#writing-tests). +3. [Check the spelling and formatting](./DEVELOPER.md#formatting) of any modified or new Fortran source files, python files definition files, markdown, and LaTeX files. +4. [Rebuild makefiles](./DEVELOPER.md#generating-makefiles) and update MSVS project files if you added, removed, or renamed any source files. +5. [Run the full test suite](./DEVELOPER.md#running-tests) and make sure all tests pass. +6. Push your branch to GitHub and create a pull request to the `develop` branch. +7. If we suggest changes: + a. make the required updates + b. make sure tests still pass + c. rebase your branch if needed + d. (force) push to update your PR That's it! Thank you for your contribution! -#### After your pull request is merged - -After your pull request is merged, you can safely delete your branch and pull the changes -from the main (upstream) repository: - -* Delete the remote branch on GitHub either through the GitHub web UI or your local shell as follows: - - ```shell - git push origin --delete my-fix-branch - ``` - -* Check out the develop branch: - - ```shell - git checkout develop -f - ``` +If you have installed the pixi environment you can complete steps 3 and 4 using: -* Delete the local branch: - - ```shell - git branch -D my-fix-branch - ``` - -* Update your develop with the latest upstream version: - - ```shell - git pull --ff upstream develop - ``` +```shell +pixi run prepare-pull-request +``` -## Coding Rules -To ensure consistency throughout the source code, keep these rules in mind as you are working: +## Source code -* All features or bug fixes **must be tested** by one or more specs (unit-tests and/or integration/regression-tests). -* All Fortran source code submissions must adhere to modflow6 [Format Rules](#format) +### Format -## Format Rules +MODFLOW 6 source code is formatted automatically with the [fprettify formatter](https://github.com/pseewald/fprettify). Format rules are specified in the [fprettify configuration file](.fprettify.yaml). See the [developer docs](./DEVELOPER.md#formatting) for instructions on using `fprettify`. -Fortran source code format rules are met by running the -[fprettify formatter](https://github.com/pseewald/fprettify) while specifying the [MODFLOW 6 fprettify configuration](.fprettify.yaml). `fprettify` is included in the conda and pixi environments and can be run on the command line or integrated into a [VSCode](.vscode/README.md) or Visual Studio environment. +### Style guide -The configuration file reflects the current minimum standard for Fortran source -formatting. The main goal, however, is consistent and readable Fortran source code and as such pay particular attention to consistency within and across files. As the formatting tool may at times shift code in unexpected ways, check for formatting consistency after running. +Automated tools like `fprettify` cannot directly address all style concerns. Please review our [style guide](https://modflow6.readthedocs.io/en/latest/styleguide.html) before submitting your code. -An example run of the command line tool from the MODFLOW 6 root directory: -`fprettify -c .fprettify.yaml ./utils/zonebudget/src/zbud6.f90` +## Commit messages -When run in this way, the tool will modify the file in place and generate no output if successful. The -tool will write stderr warnings when unable to complete formatting. In general, these warnings (e.g. -for excess line length) must be manually fixed before attempting to rerun the tool. +Adherence to commit message formatting rules results in consistent messages and a more readable project history. -Fortran source files can be excluded from the formatting standard if necessary, as is the case -for Fortran source found under the `modflow6/src/Utilities/Libraries` path. +Each commit message consists of three components: **header** (required), **body** (optional) and **footer** (optional). The header has three subcomponents: **type** (required), **scope** (optional) and **subject** (required): -## Commit Message Guidelines +See [the develop branch history](https://github.com/MODFLOW-USGS/modflow6/commits/develop) to get a sense for the commit style. -We have very precise rules over how our git commit messages can be formatted. This leads to **more -readable messages** that are easy to follow when looking through the **project history**. But also, -we use the git commit messages to **generate the MODFLOW 6 change log**. +### Template -### Commit Message Format -Each commit message consists of a **header**, a **body** and a **footer**. The header has a special -format that includes a **type**, a **scope** and a **subject**: +The general structure of a commit message is: -``` +```text (): @@ -174,63 +114,47 @@ format that includes a **type**, a **scope** and a **subject**: