From 98819acd3bbbc661d9d8da210d96b905b073baed Mon Sep 17 00:00:00 2001 From: Joseph D Hughes Date: Sun, 11 Feb 2024 14:30:22 -0600 Subject: [PATCH 1/3] update mf6 version --- autotest/ci_setup.py | 95 +++++++++++++++++++++++++++++--- autotest/test_gsflow.py | 83 ++++++++++++++++++++++++++++ autotest/test_mf6.py | 11 ++-- pymake/config.py | 4 +- pymake/utils/_usgs_src_update.py | 1 + pymake/utils/usgsprograms.txt | 7 ++- 6 files changed, 182 insertions(+), 19 deletions(-) create mode 100644 autotest/test_gsflow.py diff --git a/autotest/ci_setup.py b/autotest/ci_setup.py index ef260774..76036d76 100644 --- a/autotest/ci_setup.py +++ b/autotest/ci_setup.py @@ -1,14 +1,18 @@ import os +import pathlib as pl import shutil import pymake -temp_pth = "temp" -if not os.path.exists(temp_pth): - os.makedirs(temp_pth) -mf6_exdir = os.path.join(temp_pth, "mf6examples") -if os.path.isdir(mf6_exdir): +temp_pth = pl.Path("temp") +if not temp_pth.exists(): + temp_pth.mkdir() +mf6_exdir = temp_pth / "mf6examples" +if mf6_exdir.is_dir(): shutil.rmtree(mf6_exdir) +gsflow_exdir = temp_pth / "gsflowexamples" +if gsflow_exdir.is_dir(): + shutil.rmtree(gsflow_exdir) def download_mf6_examples(verbose=False): @@ -84,6 +88,83 @@ def examples_list(verbose=False): return +def download_gsflow_examples(verbose=False): + """Download gsflow examples and return location of folder""" + + examples_dirs = ( + "sagehen", + "acfb_dyn_params", + "acfb_water_use", + ) + + target = "gsflow" + pm = pymake.Pymake(verbose=True) + pm.target = target + + # download the gsflow release + pm.download_target(target, download_path=temp_pth) + assert pm.download, f"could not download {target} distribution" + + # get program dictionary + prog_dict = pymake.usgs_program_data.get_target(target) + + # set path to example + temp_download_dir = temp_pth / prog_dict.dirname + temp_dir = temp_download_dir / "data" + + print(f"copying files to...{gsflow_exdir}") + shutil.copytree(temp_dir, gsflow_exdir) + + # create list of examples to test and edit files if necessary + src_folders = [] + for ex_dir in examples_dirs: + out_path = gsflow_exdir / ex_dir + + if "sagehen" in ex_dir: + out_path = out_path / "linux" + modify_gsflow_sagehen(out_path) + elif "acfb" in ex_dir: + shutil.copy( + out_path / "control/control", out_path / "gsflow.control" + ) + + # add final example path to src_folders list + src_folders.append(out_path) + + print(f"removing...{temp_download_dir} directory") + shutil.rmtree(temp_download_dir) + + # create a list of gsflow examples + fpth = gsflow_exdir / "gsflowexamples.txt" + f = open(fpth, "w") + for idx, folder in enumerate(src_folders): + if verbose: + if idx == 0: + print(f"\n\nGSFLOW examples:\n{78 * '-'}") + print(f"{idx + 1:>3d}: {folder}") + f.write(f"{os.path.abspath(folder)}\n") + f.close() + + return gsflow_exdir.resolve() + + +def modify_gsflow_sagehen(temp_pth): + fpth = temp_pth / "gsflow.control" + with open(fpth) as f: + lines = f.readlines() + with open(fpth, "w") as f: + idx = 0 + while idx < len(lines): + line = lines[idx] + if "end_time" in line: + line += "6\n1\n1981\n" + idx += 3 + f.write(line) + idx += 1 + return + + if __name__ == "__main__": - mf6pth = download_mf6_examples(verbose=True) - examples_list(verbose=True) + # mf6pth = download_mf6_examples(verbose=True) + # examples_list(verbose=True) + gsflowpth = download_gsflow_examples(verbose=True) diff --git a/autotest/test_gsflow.py b/autotest/test_gsflow.py new file mode 100644 index 00000000..414e59ec --- /dev/null +++ b/autotest/test_gsflow.py @@ -0,0 +1,83 @@ +import os +from pathlib import Path +from platform import system + +import flopy +import pytest + +import pymake + +# set fpth based on current path +if os.path.basename(os.path.normpath(os.getcwd())) == "autotest": + fpth = Path("temp") +else: + fpth = Path("autotest/temp") +fpth = (fpth / "gsflowexamples/gsflowexamples.txt").resolve() +if fpth.is_file(): + with open(fpth) as f: + lines = f.read().splitlines() + sim_dirs = [line for line in lines if len(line) > 0] +else: + sim_dirs = [] + + +@pytest.fixture(scope="module") +def target(module_tmpdir) -> Path: + name = "gsflow" + ext = ".exe" if system() == "Windows" else "" + return module_tmpdir / f"{name}{ext}" + + +@pytest.fixture(scope="module") +def prog_data(target) -> dict: + return pymake.usgs_program_data.get_target(target.name) + + +@pytest.fixture(scope="module") +def workspace(module_tmpdir, prog_data) -> Path: + return module_tmpdir / prog_data.dirname + + +@pytest.fixture(scope="module") +def pm(module_tmpdir, target) -> pymake.Pymake: + pm = pymake.Pymake(verbose=True) + pm.target = str(target) + pm.appdir = module_tmpdir + pm.makefile = True + pm.makeclean = True + pm.makefiledir = module_tmpdir + pm.inplace = True + pm.networkx = True + pm.verbose = True + yield pm + pm.finalize() + + +@pytest.mark.dependency(name="download") +@pytest.mark.base +def test_download(pm, module_tmpdir, target): + pm.download_target(target, download_path=module_tmpdir) + assert pm.download, f"could not download {target} distribution" + + +@pytest.mark.dependency(name="build", depends=["download"]) +@pytest.mark.base +def test_compile(pm, target): + assert pm.build() == 0, f"could not compile {target}" + + +@pytest.mark.dependency(name="test", depends=["build"]) +@pytest.mark.regression +@pytest.mark.parametrize("ws", sim_dirs) +def test_gsflow(ws, target): + success, _ = flopy.run_model( + target, + "gsflow.control", + model_ws=ws, + silent=False, + normal_msg=[ + "normal termination", + "Normal completion of GSFLOW", + ], + ) + assert success, f"could not run {ws}" diff --git a/autotest/test_mf6.py b/autotest/test_mf6.py index 5358f45a..b9470f64 100644 --- a/autotest/test_mf6.py +++ b/autotest/test_mf6.py @@ -12,14 +12,11 @@ # set fpth based on current path if os.path.basename(os.path.normpath(os.getcwd())) == "autotest": - fpth = os.path.abspath( - os.path.join("temp", "mf6examples", "mf6examples.txt") - ) + fpth = Path("temp") else: - fpth = os.path.abspath( - os.path.join("autotest", "temp", "mf6examples", "mf6examples.txt") - ) -if os.path.isfile(fpth): + fpth = Path("autotest/temp") +fpth = (fpth / "mf6examples/mf6examples.txt").resolve() +if fpth.is_file(): with open(fpth) as f: lines = f.read().splitlines() sim_dirs = [line for line in lines if len(line) > 0] diff --git a/pymake/config.py b/pymake/config.py index c558bcf5..b1f377ab 100644 --- a/pymake/config.py +++ b/pymake/config.py @@ -1,6 +1,6 @@ __author__ = "Joseph D. Hughes" -__date__ = "July 5, 2023" -__version__ = "1.2.9.dev0" +__date__ = "February 11, 2024" +__version__ = "1.2.9" __maintainer__ = "Joseph D. Hughes" __email__ = "jdhughes@usgs.gov" __status__ = "Production" diff --git a/pymake/utils/_usgs_src_update.py b/pymake/utils/_usgs_src_update.py index 1b3be914..0bca9acc 100644 --- a/pymake/utils/_usgs_src_update.py +++ b/pymake/utils/_usgs_src_update.py @@ -881,6 +881,7 @@ def _update_mf6_external_dependencies( "Utilities/Matrix/PetscMatrix.F90", "Solution/PETSc/PetscSolver.F90", "Solution/PETSc/PetscConvergence.F90", + "Solution/PETSc//PetscImsPreconditioner.F90", "Distributed/MpiMessageBuilder.f90", "Distributed/MpiRouter.f90", "Distributed/MpiRunControl.F90", diff --git a/pymake/utils/usgsprograms.txt b/pymake/utils/usgsprograms.txt index 37e66936..4af573dc 100644 --- a/pymake/utils/usgsprograms.txt +++ b/pymake/utils/usgsprograms.txt @@ -1,7 +1,7 @@ target , version, current, url , dirname , srcdir , standard_switch, double_switch, shared_object -mf6 , 6.4.2 , True , https://github.com/MODFLOW-USGS/modflow6/releases/download/6.4.2/mf6.4.2_linux.zip , mf6.4.2_linux , src , True , False , False -zbud6 , 6.4.2 , True , https://github.com/MODFLOW-USGS/modflow6/releases/download/6.4.2/mf6.4.2_linux.zip , mf6.4.2_linux , utils/zonebudget/src, True , False , False -libmf6 , 6.4.2 , True , https://github.com/MODFLOW-USGS/modflow6/releases/download/6.4.2/mf6.4.2_linux.zip , mf6.4.2_linux , srcbmi , True , False , True +mf6 , 6.4.3 , True , https://github.com/MODFLOW-USGS/modflow6/releases/download/6.4.3/mf6.4.3_linux.zip , mf6.4.3_linux , src , True , False , False +zbud6 , 6.4.3 , True , https://github.com/MODFLOW-USGS/modflow6/releases/download/6.4.3/mf6.4.3_linux.zip , mf6.4.3_linux , utils/zonebudget/src, True , False , False +libmf6 , 6.4.3 , True , https://github.com/MODFLOW-USGS/modflow6/releases/download/6.4.3/mf6.4.3_linux.zip , mf6.4.3_linux , srcbmi , True , False , True mp7 , 7.2.001, True , https://water.usgs.gov/water-resources/software/MODPATH/modpath_7_2_001.zip , modpath_7_2_001 , source , True , False , False mt3dms , 5.3.0 , True , https://github.com/MODFLOW-USGS/mt3dms/releases/download/2.0/mt3dms-2.0.zip , mt3dms-2.0 , true-binary , True , False , False mt3dusgs , 1.1.0 , True , https://water.usgs.gov/water-resources/software/MT3D-USGS/mt3dusgs1.1.0.zip , mt3dusgs1.1.0 , src , True , False , False @@ -21,6 +21,7 @@ zonbud3 , 3.01 , True , https://water.usgs.gov/water-resources/software mfnwt1.1.4 , 1.1.4 , False , https://water.usgs.gov/water-resources/software/MODFLOW-NWT/MODFLOW-NWT_1.1.4.zip , MODFLOW-NWT_1.1.4 , src , True , False , False mfnwt , 1.3.0 , True , https://water.usgs.gov/water-resources/software/MODFLOW-NWT/MODFLOW-NWT_1.3.0.zip , MODFLOW-NWT , src , True , False , False mfusg_gsi , 2.2.2 , True , https://www.gsienv.com/wp-content/uploads/2023/11/USG-Transport_Version-2.2.2.zip , USGT-v2-2-2-Source , . , True , False , False +gsflow , 2.2.1 , True , https://water.usgs.gov/water-resources/software/gsflow/gsflow_2.2.1_linux.zip , gsflow_2.2.1 , src , True , False , False mf6dev , 6.5.0.dev0 , False , https://github.com/MODFLOW-USGS/modflow6/archive/refs/heads/develop.zip , modflow6-develop , src , True , False , False zbud6dev , 6.5.0.dev0 , False , https://github.com/MODFLOW-USGS/modflow6/archive/refs/heads/develop.zip , modflow6-develop , utils/zonebudget/src, True , False , False libmf6dev , 6.5.0.dev0 , False , https://github.com/MODFLOW-USGS/modflow6/archive/refs/heads/develop.zip , modflow6-develop , srcbmi , True , False , True \ No newline at end of file From eefb7191b359a925e305f2d0b78796d0c5c97271 Mon Sep 17 00:00:00 2001 From: Joseph D Hughes Date: Sun, 11 Feb 2024 15:17:41 -0600 Subject: [PATCH 2/3] update to use BINARY option for windows builds with ifort --- autotest/ci_setup.py | 4 ++-- pymake/pymake_base.py | 32 ++++++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/autotest/ci_setup.py b/autotest/ci_setup.py index 76036d76..e77b66db 100644 --- a/autotest/ci_setup.py +++ b/autotest/ci_setup.py @@ -165,6 +165,6 @@ def modify_gsflow_sagehen(temp_pth): if __name__ == "__main__": - # mf6pth = download_mf6_examples(verbose=True) - # examples_list(verbose=True) + mf6pth = download_mf6_examples(verbose=True) + examples_list(verbose=True) gsflowpth = download_gsflow_examples(verbose=True) diff --git a/pymake/pymake_base.py b/pymake/pymake_base.py index 653ed6bc..9278c4d3 100644 --- a/pymake/pymake_base.py +++ b/pymake/pymake_base.py @@ -271,15 +271,21 @@ def main( if not meson: if _get_osname() == "win32": if fc is not None: - if fc in ["ifort", "mpiifort"]: + if fc in ( + "ifort", + "mpiifort", + ): intelwin = True if cc is not None: - if cc in ["cl", "icl"]: + if cc in ( + "cl", + "icl", + ): intelwin = True # update openspec files based on intelwin if not intelwin: - _create_openspec(srcfiles, verbose) + _create_openspec(intelwin, srcfiles, verbose) # compile the executable if meson: @@ -666,13 +672,20 @@ def _clean_temp_files( return -def _create_openspec(srcfiles, verbose): +def _create_openspec(intelwin, srcfiles, verbose): """Create new openspec.inc, FILESPEC.INC, and filespec.inc files that uses STREAM ACCESS. This is specific to MODFLOW and MT3D based targets. Source directories are scanned and files defining file access are replaced. Parameters ---------- + intelwin : bool + boolean indicating if source files are being built on Windows using + intel compilers. + srcfiles : list + list of source files to be compiled + verbose: bool + boolean indicating if output will be printed to the terminal Returns ------- @@ -697,11 +710,18 @@ def _create_openspec(srcfiles, verbose): if verbose: print(f'replacing..."{fpth}"') f = open(fpth, "w") + if intelwin: + data_access = "SEQUENTIAL" + data_form = "BINARY" + else: + data_access = "STREAM" + data_form = "UNFORMATTED" + line = ( "c -- created by pymake_base.py\n" + " CHARACTER*20 ACCESS,FORM,ACTION(2)\n" - + " DATA ACCESS/'STREAM'/\n" - + " DATA FORM/'UNFORMATTED'/\n" + + f" DATA ACCESS/'{data_access}'/\n" + + f" DATA FORM/'{data_form}'/\n" + " DATA (ACTION(I),I=1,2)/'READ','READWRITE'/\n" + "c -- end of include file\n" ) From 48b0589391273090b1d58c295eae9e7694205620 Mon Sep 17 00:00:00 2001 From: Joseph D Hughes Date: Sun, 11 Feb 2024 15:44:16 -0600 Subject: [PATCH 3/3] update zbud6 include files --- pymake/pymake.py | 8 ++++++-- pymake/pymake_base.py | 1 - 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/pymake/pymake.py b/pymake/pymake.py index 6d62f121..ac84737c 100644 --- a/pymake/pymake.py +++ b/pymake/pymake.py @@ -598,16 +598,20 @@ def _set_extrafiles(self): "../../../src/Utilities/Budget.f90", "../../../src/Utilities/Constants.f90", "../../../src/Utilities/compilerversion.F90", - "../../../src/Utilities/genericutils.f90", + "../../../src/Utilities/ErrorUtil.f90", + "../../../src/Utilities/GeomUtil.f90", + "../../../src/Utilities/MathUtil.f90", "../../../src/Utilities/InputOutput.f90", "../../../src/Utilities/kind.f90", + "../../../src/Utilities/LongLineReader.f90", "../../../src/Utilities/OpenSpec.f90", "../../../src/Utilities/sort.f90", - "../../../src/Utilities/Message.f90", "../../../src/Utilities/defmacro.F90", "../../../src/Utilities/Sim.f90", "../../../src/Utilities/SimVariables.f90", "../../../src/Utilities/version.f90", + "../../../src/Utilities/DevFeature.f90", + "../../../src/Utilities/Message.f90", ] # evaluate extrafiles type diff --git a/pymake/pymake_base.py b/pymake/pymake_base.py index 9278c4d3..1a1a282b 100644 --- a/pymake/pymake_base.py +++ b/pymake/pymake_base.py @@ -727,7 +727,6 @@ def _create_openspec(intelwin, srcfiles, verbose): ) f.write(line) f.close() - return def _check_out_of_date(srcfile, objfile):