From 8ba26e45b30895ab9abeefaf6d791aa96c4dba35 Mon Sep 17 00:00:00 2001 From: Andreas Holm <60451789+holm10@users.noreply.github.com> Date: Thu, 11 Jul 2024 12:25:55 -0700 Subject: [PATCH] Updates build and test workflows - Adds pyproject.toml for building w/ PIP - Modifies build to use Forthon compatible w/ numpy >2.0 - Hardens tests and wheel builds - Removes Py3.7 builds (EOL) --- .github/workflows/build-test-wheel.yml | 210 +++++++++++++++++++++++ .github/workflows/run_testsuite.yml | 163 ------------------ Makefile.Forthon | 2 +- {pyscripts => buildscripts}/convert.py | 0 {pyscripts => buildscripts}/filelists.py | 0 pyproject.toml | 84 +++++++++ pyscripts/__init__.py | 36 ---- pyscripts/bas2py | 41 ++++- pyscripts/checkver.py | 38 ---- setup.py | 174 +++++++++---------- {pyscripts => src/uedge}/Makefile.am | 0 src/uedge/VERSION | 1 + src/uedge/__init__.py | 25 +++ {pyscripts => src/uedge}/cdf4.py | 0 src/uedge/checkver.py | 28 +++ {pyscripts => src/uedge}/convert1.py | 0 {pyscripts => src/uedge}/defaults.yaml | 0 src/uedge/filelists.py | 17 ++ {pyscripts => src/uedge}/gridue.py | 0 {pyscripts => src/uedge}/hdf5.py | 0 {pyscripts => src/uedge}/rundt.py | 16 +- {pyscripts => src/uedge}/sources.py | 0 {pyscripts => src/uedge}/uedge.py | 0 {pyscripts => src/uedge}/uedge_lists.py | 0 {pyscripts => src/uedge}/uedgeplots.py | 0 25 files changed, 500 insertions(+), 335 deletions(-) create mode 100644 .github/workflows/build-test-wheel.yml delete mode 100644 .github/workflows/run_testsuite.yml rename {pyscripts => buildscripts}/convert.py (100%) rename {pyscripts => buildscripts}/filelists.py (100%) create mode 100644 pyproject.toml delete mode 100755 pyscripts/__init__.py delete mode 100644 pyscripts/checkver.py rename {pyscripts => src/uedge}/Makefile.am (100%) create mode 100644 src/uedge/VERSION create mode 100755 src/uedge/__init__.py rename {pyscripts => src/uedge}/cdf4.py (100%) create mode 100644 src/uedge/checkver.py rename {pyscripts => src/uedge}/convert1.py (100%) rename {pyscripts => src/uedge}/defaults.yaml (100%) create mode 100755 src/uedge/filelists.py rename {pyscripts => src/uedge}/gridue.py (100%) rename {pyscripts => src/uedge}/hdf5.py (100%) rename {pyscripts => src/uedge}/rundt.py (98%) rename {pyscripts => src/uedge}/sources.py (100%) rename {pyscripts => src/uedge}/uedge.py (100%) rename {pyscripts => src/uedge}/uedge_lists.py (100%) rename {pyscripts => src/uedge}/uedgeplots.py (100%) diff --git a/.github/workflows/build-test-wheel.yml b/.github/workflows/build-test-wheel.yml new file mode 100644 index 00000000..20a694ec --- /dev/null +++ b/.github/workflows/build-test-wheel.yml @@ -0,0 +1,210 @@ +name: Build and test UEDGE - write wheel files if tests pass + + +on: [push, pull_request] + +jobs: + run-all-tests: + name: Runs test ${{ matrix.tests }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: [3.9] + tests: [fulltests, unittests/D+C, unittests/D_mols, unittests/D_only, unittests/slab_D_only] + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + - name: Install pip dependencies + run: | + python -m pip install --upgrade pip + python -m pip install "forthon>=0.10.7" numpy h5py + python -m pip install flake8 + python -m pip install pytest-isolate pytest-xdist + - name: Build UEDGE + run: | + python -m pip install . + - name: Return to pytests branch + uses: actions/checkout@v4 + with: + ref: pytests + repository: LLNL/UEDGE + - name: Test with pytest + run: | + # Create a clean UEDGE instance for every test + pytest --isolate --tb=native pytests/${{ matrix.tests }} + + + build_wheels: + name: Build wheels on ${{ matrix.os }} for Python ${{ matrix.pyver }} + # if: github.event_name == 'pull_request' + needs: run-all-tests + runs-on: ${{ matrix.os }} + continue-on-error: true + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-13, macos-14] + pyver: [cp38, cp39, cp310, cp311, cp312] + + steps: + - name: Checks out repo + uses: actions/checkout@v4 + + - name: Symlink gfortran for x86 macOS + if: matrix.os == 'macos-13' + run: | + # make sure gfortran is available + ln -s /usr/local/bin/gfortran-13 /usr/local/bin/gfortran + gfortran --version + + + - name: Symlink gfortran for ARM macOS + if: matrix.os == 'macos-14' + run: | + # make sure gfortran is available + ln -s /opt/homebrew/bin/gfortran-13 /opt/homebrew/bin/gfortran + gfortran --version + + - name: Build wheels + if: ${{ !(matrix.os == 'macos-14' && matrix.pyver == 'cp37') }} + uses: pypa/cibuildwheel@v2.17.0 + env: + CIBW_BUILD: ${{matrix.pyver}}-* + CIBW_ARCHS_LINUX: auto + CIBW_SKIP: "pp37-* cp37-* *-win32 *-manylinux_i686" + CIBW_BEFORE_BUILD: pip install numpy 'forthon>=0.10.7' 'build<0.10.0' + + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + name: cibw-wheels-${{ matrix.os }}-${{ matrix.pyver }}-${{ strategy.job-index }} + path: ./wheelhouse/*.whl + + build_wheels_pypy: + name: Build PyPy wheels on ${{ matrix.os }} +# if: github.event_name == 'pull_request' + needs: run-all-tests + runs-on: ${{ matrix.os }} + continue-on-error: true + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-13, macos-14] + + steps: + - name: Checks out repo + uses: actions/checkout@v4 + + - name: Symlink gfortran for x86 macOS + if: matrix.os == 'macos-13' + run: | + # make sure gfortran is available + ln -s /usr/local/bin/gfortran-13 /usr/local/bin/gfortran + gfortran --version + + + - name: Symlink gfortran for ARM macOS + if: matrix.os == 'macos-14' + run: | + # make sure gfortran is available + ln -s /opt/homebrew/bin/gfortran-13 /opt/homebrew/bin/gfortran + gfortran --version + + - name: Build wheels + uses: pypa/cibuildwheel@v2.17.0 + env: + CIBW_BUILD: pp* + CIBW_SKIP: "pp37-* cp37-* *-win32 *-manylinux_i686" + CIBW_BEFORE_BUILD: pip install numpy 'forthon>=0.10.7' 'build<0.10.0' + + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + name: cibw-wheels-pyp-${{ matrix.os }}-${{ strategy.job-index }} + path: ./wheelhouse/*.whl + + + build_wheels_cross: + name: Build Linux cross-wheels + if: false +# needs: run-all-tests + runs-on: ubuntu-latest + continue-on-error: true + strategy: + fail-fast: false + matrix: + pyver: [cp38, cp39, cp310, cp311, cp312] + arch: [aarch64, ppc64le] + + steps: + - name: Checks out repo + uses: actions/checkout@v4 + + - name: Set up QEMU for multi-arch build + uses: docker/setup-qemu-action@v2 + + - name: Build wheels + uses: pypa/cibuildwheel@v2.17.0 + env: + CIBW_BUILD: ${{matrix.pyver}}-* + CIBW_ARCHS: ${{matrix.arch}} + CIBW_SKIP: "pp37-* cp37-* *-win32 *-manylinux_i686" + CIBW_BEFORE_BUILD: pip install numpy 'forthon>=0.10.7' 'build<0.10.0' + + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + name: cibw-cross-wheels-${{ matrix.arch }}-${{ matrix.pyver }}-${{ strategy.job-index }} + path: ./wheelhouse/*.whl + + build_wheels_cross_pypy: + name: Build Linux PyPy cross-wheels + if: false +# needs: run-all-tests + runs-on: ubuntu-latest + continue-on-error: true + strategy: + fail-fast: false + + steps: + - name: Checks out repo + uses: actions/checkout@v4 + + - name: Set up QEMU for multi-arch build + uses: docker/setup-qemu-action@v2 + + - name: Build wheels + uses: pypa/cibuildwheel@v2.17.0 + env: + CIBW_BUILD: pp* + CIBW_SKIP: "pp37-* cp37-* *-win32 *-manylinux_i686" + CIBW_BEFORE_BUILD: pip install numpy 'forthon>=0.10.7' 'build<0.10.0' + + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + name: cibw-cross-wheels-pypy-${{ strategy.job-index }} + path: ./wheelhouse/*.whl + + + gather_wheels: + name: Gather built wheels + needs: [build_wheels, build_wheels_pypy] +# if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + steps: + - name: Download all Artifacts and merges them + uses: actions/download-artifact@v4 + with: + path: wheels + merge-multiple: true + + - name: Upload all Artifacts in a single Archive + uses: actions/upload-artifact@v4 + with: + name: all_wheels + path: wheels diff --git a/.github/workflows/run_testsuite.yml b/.github/workflows/run_testsuite.yml deleted file mode 100644 index 2e28535d..00000000 --- a/.github/workflows/run_testsuite.yml +++ /dev/null @@ -1,163 +0,0 @@ -# This workflow will install Python dependencies, run tests and lint with a variety of Python versions -# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions - -name: Build UEDGE and run test suite - -on: [push, pull_request] - -jobs: - fulltests: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: [3.9] - steps: - - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - - name: Install pip dependencies - run: | - python -m pip install --upgrade pip - python -m pip install forthon mppl numpy h5py - python -m pip install flake8 - python -m pip install pytest-isolate pytest-xdist - - name: Build UEDGE - run: | - python setup.py build - python setup.py install - - name: Return to pytests branch - uses: actions/checkout@v4 - with: - ref: pytests - repository: LLNL/UEDGE - - name: Test with pytest - run: | - # Create a clean UEDGE instance for every test - pytest --isolate --tb=native pytests/fulltests - - unittests_D-and-C: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: [3.9] - steps: - - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - - name: Install pip dependencies - run: | - python -m pip install --upgrade pip - python -m pip install forthon mppl numpy h5py - python -m pip install flake8 - python -m pip install pytest-isolate pytest-xdist - - name: Build UEDGE - run: | - python setup.py build - python setup.py install - - name: Return to pytests branch - uses: actions/checkout@v4 - with: - ref: pytests - repository: LLNL/UEDGE - - name: Test with pytest - run: | - # Create a clean UEDGE instance for every test - pytest --isolate --tb=native pytests/unittests/D+C - - unittests_D-mols: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: [3.9] - steps: - - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - - name: Install pip dependencies - run: | - python -m pip install --upgrade pip - python -m pip install forthon mppl numpy h5py - python -m pip install flake8 - python -m pip install pytest-isolate pytest-xdist - - name: Build UEDGE - run: | - python setup.py build - python setup.py install - - name: Return to pytests branch - uses: actions/checkout@v4 - with: - ref: pytests - repository: LLNL/UEDGE - - name: Test with pytest - run: | - # Create a clean UEDGE instance for every test - pytest --isolate --tb=native pytests/unittests/D_mols - - unittests_D-only: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: [3.9] - steps: - - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - - name: Install pip dependencies - run: | - python -m pip install --upgrade pip - python -m pip install forthon mppl numpy h5py - python -m pip install flake8 - python -m pip install pytest-isolate pytest-xdist - - name: Build UEDGE - run: | - python setup.py build - python setup.py install - - name: Return to pytests branch - uses: actions/checkout@v4 - with: - ref: pytests - repository: LLNL/UEDGE - - name: Test with pytest - run: | - # Create a clean UEDGE instance for every test - pytest --isolate --tb=native pytests/unittests/D_only - - unittests_slab-D-only: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: [3.9] - steps: - - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - - name: Install pip dependencies - run: | - python -m pip install --upgrade pip - python -m pip install forthon mppl numpy h5py - python -m pip install flake8 - python -m pip install pytest-isolate pytest-xdist - - name: Build UEDGE - run: | - python setup.py build - python setup.py install - - name: Return to pytests branch - uses: actions/checkout@v4 - with: - ref: pytests - repository: LLNL/UEDGE - - name: Test with pytest - run: | - # Create a clean UEDGE instance for every test - pytest --isolate --tb=native pytests/unittests/slab_D_only - diff --git a/Makefile.Forthon b/Makefile.Forthon index df1b6129..62cbdc6e 100644 --- a/Makefile.Forthon +++ b/Makefile.Forthon @@ -13,7 +13,7 @@ all: mppl2f90 $(BUILDDIR)/compydep $(BUILDDIR)/grdpydep $(BUILDDIR)/flxpydep $(B rm -f uedgeC.so mppl2f90: - (export PYTHONPATH=.:./pyscripts; $(MYPYTHON) convertor) + (export PYTHONPATH=.:./buildscripts; $(MYPYTHON) convertor) $(BUILDDIR)/compydep: com/blasext.F com/brent.F com/comutil.F com/misc.F com/mnbrak.F com/dsum.f com/dummy_py.f com/error.f com/getmsg.f com/ssum.f com/$(PETSC-COM) com/com.v $(FORTHON) -a $(INSTALLARGS) -a $(FCOMP) $(DEBUG) --interfacefile com/com.v -f com/blasext.F com com/brent.F com/comutil.F com/misc.F com/mnbrak.F com/dsum.f com/dummy_py.f com/error.f com/getmsg.f com/ssum.f $(PETSC-COM) diff --git a/pyscripts/convert.py b/buildscripts/convert.py similarity index 100% rename from pyscripts/convert.py rename to buildscripts/convert.py diff --git a/pyscripts/filelists.py b/buildscripts/filelists.py similarity index 100% rename from pyscripts/filelists.py rename to buildscripts/filelists.py diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..dea951a1 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,84 @@ +[build-system] +requires = [ + "setuptools >= 61.0", + "forthon>=0.10.7", + "numpy" + ] +build-backend = "setuptools.build_meta" + +[project] +# TODO: Make version dynamic! +dynamic = ["version"] +#version = "8.1.0-beta.0" +name = "uedge" +dependencies = [ + "forthon>=0.10.7", + "numpy" +] +requires-python = ">= 3.7" # TODO: verify +authors = [ + {name = "Tom Rognlien"} +] +maintainers = [ + {name = "Bill Meyer", email = "meyer8@llnl.gov"}, + {name = "Andreas Holm", email = "holm10@llnl.gov"} +] +description = "2D Fluid simulation of plasma and neutrals in magnetic fusion devices" +readme = "README.md" +keywords = [ + "plasma", + "fusion", + "tokamak", + "edge-plasma", + "scrape-off layer", + "multi-fluid" +] +classifiers = [ + "Intended Audience :: Science/Research", + "License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)", + "Operating System :: Unix", + "Operating System :: MacOS :: MacOS X", + "Programming Language :: Fortran", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Topic :: Scientific/Engineering :: Physics", +] + +[project.urls] +Homepage = "https://github.com/LLNL/UEDGE/" +#Documentation = "https://readthedocs.org" +Repository = "https://github.com/LLNL/UEDGE.git" +Issues = "https://github.com/LLNL/UEDGE/issues" +#Changelog = "https://github.com/me/spam/blob/master/CHANGELOG.md" + + + + +[project.optional-dependencies] +ueplot = [ + "matplotlib", + "scipy", + "scikit-image", + "h5py", +] + +# TODO: rewrite scripts to be importable +#[project.scripts] +#spam-cli = "spam:main_cli" + +# TODO: add scripts to separate folder +[tool.setuptools] +script-files = [ + "pyscripts/pdb2hdf5", + "pyscripts/bas2py", + "pyscripts/hdf52pdb", +] +#packages = ["uedge"] +#package-dir = {"" = "pyscripts"} + + + +[tool.setuptools.dynamic] +#version = {attr = "uedge.__version__"} +version = {file = ["src/uedge/VERSION"]} +#version = {file = "VERSION"} diff --git a/pyscripts/__init__.py b/pyscripts/__init__.py deleted file mode 100755 index c86b9699..00000000 --- a/pyscripts/__init__.py +++ /dev/null @@ -1,36 +0,0 @@ -from .uedge import * -from os import path -from pathlib import Path -try: - from uedge.__version__ import __version__ - from uedge.__src__ import __src__ - import uedge.checkver -except: - try: - from __version__ import __version__ - from __src__ import __src__ - import checkver - except: - __version__ = 'unknown' - __src__ = 'unknown' - -# -# Load the startup file .uedgerc.py from cwd or home. -# -_homepath = path.expanduser('~') -_homefile = Path('{}/.uedgerc.py'.format(_homepath)) -_localpath = path.expanduser('.') -_localfile = Path('{}/.uedgerc.py'.format(_localpath)) - -if path.exists(_localfile): - with open(_localfile) as f: - exec(open(_localfile).read()) -elif path.exists(_homefile): - with open(_homefile) as f: - exec(open(_homefile).read()) - -# -# Ensure that the UEDGE internal version matches the Python release -# - -uedge.bbb.uedge_ver = __version__ diff --git a/pyscripts/bas2py b/pyscripts/bas2py index cf37eb70..7cead4ea 100755 --- a/pyscripts/bas2py +++ b/pyscripts/bas2py @@ -4,10 +4,10 @@ import numpy as np import sys,os,inspect import re import logging -try: - from uedge import bas2py_rules -except: - import bas2py_rules +#try: +# from uedge import bas2py_rules +#except: +# import bas2py_rules logger = logging.getLogger('bas2py') logging.basicConfig() @@ -17,6 +17,39 @@ sys.path.append(mydir) infile = None outfile = None +from uedge import * +import uedge.uedge_lists as ul +subrules = [ + ['\(','['], + ['\)',']'], + [';','\n'], + ['^!','#!'], + ['^ *',''], + ['^\t*',''], + [r'\ballocate\b','bbb.allocate()'], + [r'\bexmain\b','bbb.exmain()'], + [r'\bexponseed\b','grd.exponseed()'], + ] +warnrules = [] +def raw_string(s): + s = s.encode('unicode-escape').decode() + return s + +for p in ul.list_packages(): + subrules.append([r'\b'+raw_string('package '+ p)+r'\b','from uedge import '+p]) + po = ul.packagename2object(p) + for v in ul.list_package_variables(p): + subrules.append([r'\b'+raw_string(v)+r'\b',p+'.'+v]) + + if "Dimension:" in po.listvar(v): + d = po.listvar(v).split("Dimension:")[1].split("\n") + if "0:" in d[0]: + warnrules.append([r'\b'+raw_string(v)+r'\b','base 0, '+d[0]]) + + + +subrules.append([r'\bbbb.del\b','bbb.delpy']) + if __name__ == "__main__": diff --git a/pyscripts/checkver.py b/pyscripts/checkver.py deleted file mode 100644 index 9b4195d1..00000000 --- a/pyscripts/checkver.py +++ /dev/null @@ -1,38 +0,0 @@ - -import json - -pkg = 'uedge' - -try: - import importlib.metadata - thisver = importlib.metadata.version(pkg) -except: - import pkg_resources - thisver = pkg_resources.get_distribution(pkg).version - -try: - import urllib.request - contents = urllib.request.urlopen('https://pypi.org/pypi/'+pkg+'/json').read() - data = json.loads(contents.decode()) - thatver = data['info']['version'] -except: - import urllib - contents = urllib.urlopen('https://pypi.org/pypi/'+pkg+'/json').read() - data = json.loads(contents) - thatver = str(data['info']['version']) - - -if thisver > thatver: - #print('Uedge version '+thisver+' is newer than available with pip ('+thatver+')') - pass -elif thisver == thatver: - #print('Uedge version '+thisver+' is up-to-date') - pass -elif thisver < thatver: - print() - print('Uedge version '+thisver+', an update is available to '+thatver) - print() -else: - print() - print('Some error checking pypi version') - print() diff --git a/setup.py b/setup.py index eb4ac85c..ccb7a4ff 100644 --- a/setup.py +++ b/setup.py @@ -10,29 +10,26 @@ from Forthon.compilers import FCompiler import getopt import logging - -version='8.1.0-beta.0' - +from subprocess import call +import numpy try: - os.environ['PATH'] += os.pathsep + site.USER_BASE + '/bin' - import setuptools - import distutils - from distutils.core import setup - from distutils.core import Extension + from setuptools import Extension, setup, Distribution + from setuptools.command.build import build +# from setuptools.command.develop import develop +# from setuptools.command.egg_info import egg_info +except: + from distutils.core import Extension, setup from distutils.dist import Distribution from distutils.command.build import build - from distutils.command.install import install - from subprocess import call - import numpy -except: - raise SystemExit("Distutils problem") +os.environ['PATH'] += os.pathsep + site.USER_BASE + '/bin' + -optlist, args = getopt.getopt(sys.argv[1:], 'gt:F:', ['parallel', 'petsc', 'omp']) +optlist, args = getopt.getopt(sys.argv[1:], 'gt:F:', ['parallel', 'omp']) machine = sys.platform debug = 0 fcomp = None parallel = 0 -petsc = 0 +#petsc = 0 for o in optlist: if o[0] == '-g': @@ -43,19 +40,19 @@ fcomp = o[1] elif o[0] == '--parallel': parallel = 1 - elif o[0] == '--petsc': - petsc = 1 +# elif o[0] == '--petsc': +# petsc = 1 elif o[0] == '--omp': os.putenv("OMP","1") -if petsc == 1 and os.getenv('PETSC_DIR') == None: - raise SystemExit("PETSc requested but PETSC_DIR not set") -if os.getenv('PETSC_DIR') != None: - petsc = 1 -if petsc == 1 and os.getenv('PETSC_ARCH') == None: - raise SystemExit("PETSc requested but PETSC_ARCH not set") +#if petsc == 1 and os.getenv('PETSC_DIR') == None: +# raise SystemExit("PETSc requested but PETSC_DIR not set") +#if os.getenv('PETSC_DIR') != None: +# petsc = 1 +#if petsc == 1 and os.getenv('PETSC_ARCH') == None: +# raise SystemExit("PETSc requested but PETSC_ARCH not set") sys.argv = ['setup2.py']+args @@ -64,36 +61,53 @@ fcompname=fcomp) -class uedgeInstall(build): - def run(self): - install.run(self) - logging.basicConfig(stream=sys.stderr,level=logging.INFO) - log = logging.getLogger() - log.info("test") +#class uedgeInstall(build): +# def run(self): +# install.run(self) +# logging.basicConfig(stream=sys.stderr,level=logging.INFO) +# log = logging.getLogger() +# log.info("test") + class uedgeBuild(build): def run(self): + print("Building UEDGE...") # with python2 everything is put into a single uedgeC.so file if sys.hexversion < 0x03000000: raise SystemExit("Python versions < 3 not supported") else: - if petsc == 0: - status = call(['make', '-f','Makefile.Forthon']) - else: - status = call(['make', '-f', 'Makefile.PETSc']) - if status != 0: raise SystemExit("Build failure") +# if petsc == 0: + status = call(['make', '-f','Makefile.Forthon']) +# else: +# status = call(['make', '-f', 'Makefile.PETSc']) + if status != 0: + raise SystemExit("Build failure") build.run(self) class uedgeClean(build): def run(self): + print("Cleaning UEDGE") if sys.hexversion < 0x03000000: raise SystemExit("Python versions < 3 not supported") else: - if petsc == 0: - status = call(['make', '-f', 'Makefile.Forthon', 'clean']) - else: - status = call(['make', '-f', 'Makefile.PETSc', 'clean']) - if status != 0: raise SystemExit("Clean failure") +# if petsc == 0: + status = call(['make', '-f', 'Makefile.Forthon', 'clean']) +# else: +# status = call(['make', '-f', 'Makefile.PETSc', 'clean']) + if status != 0: + raise SystemExit("Clean failure") + + +#class CustomDevelopCommand(develop): +# def run(self): +# print("Develop called") +# develop.run(self) + + +#class CustomEggInfoCommand(egg_info): +# def run(self): +# print("EggInfo called") +# egg_info.run(self) uedgepkgs = ['aph', 'api', 'bbb', 'com', 'flx', 'grd', 'svr', 'wdf', 'ncl'] @@ -126,27 +140,27 @@ def makeobjects(pkg): library_dirs = fcompiler.libdirs libraries = fcompiler.libs -if petsc: +#if petsc: # PETSC_DIR = '/homes/mccomic/petsc-uedge' # PETSC_ARCH = 'linux-uedge' - PETSC_DIR = os.getenv('PETSC_DIR') - PETSC_ARCH = os.getenv('PETSC_ARCH') - library_dirs = fcompiler.libdirs + \ - [os.path.join(PETSC_DIR, PETSC_ARCH, 'lib')] - libraries = ['petscts', 'petscsnes', 'petscksp', 'petscdm', 'petscmat', - 'petscvec', 'petsc', 'HYPRE', 'mpich', 'lapack', 'blas', 'X11', - 'pthread', 'rt', 'stdc++', 'm'] + fcompiler.libs - libraries = ['petsc'] + fcompiler.libs +# PETSC_DIR = os.getenv('PETSC_DIR') +# PETSC_ARCH = os.getenv('PETSC_ARCH') +# library_dirs = fcompiler.libdirs + \ +# [os.path.join(PETSC_DIR, PETSC_ARCH, 'lib')] +# libraries = ['petscts', 'petscsnes', 'petscksp', 'petscdm', 'petscmat', +# 'petscvec', 'petsc', 'HYPRE', 'mpich', 'lapack', 'blas', 'X11', +# 'pthread', 'rt', 'stdc++', 'm'] + fcompiler.libs +# libraries = ['petsc'] + fcompiler.libs if parallel: library_dirs = fcompiler.libdirs + ['/usr/lpp/ppe.poe/lib'] libraries = fcompiler.libs + ['mpi'] # uedgeobjects = uedgeobjects + ['/usr/local/mpi/ifc_farg.o'] -with open('pyscripts/__version__.py','w') as ff: - ff.write("__version__ = '%s'\n"%version) -with open('pyscripts/__src__.py','w') as ff: - ff.write("__src__ = '%s'\n"%os.getcwd()) +#with open('pyscripts/__version__.py','w') as ff: +# ff.write("__version__ = '%s'\n"%version) +#with open('pyscripts/__src__.py','w') as ff: +# ff.write("__src__ = '%s'\n"%os.getcwd()) define_macros=[("WITH_NUMERIC", "0"), ("FORTHON_PKGNAME", '\"uedgeC\"'), @@ -161,37 +175,25 @@ def makeobjects(pkg): libraries = ['readline'] + libraries -setup(name="uedge", - version=version, - author='Tom Rognlien', - author_email="trognlien@llnl.gov", - maintainer='Bill Meyer', - maintainer_email='meyer8@llnl.gov', - description="2D Fluid simulation of plasma and neutrals in magnetic fusion devices", - platforms="Unix, Windows (cygwin), Mac OSX", - packages=['uedge'], - package_dir={'uedge': 'pyscripts'}, - # include_package_data=True, - scripts=['pyscripts/pdb2hdf5', 'pyscripts/bas2py', 'pyscripts/hdf52pdb'], - ext_modules=[Extension('uedge.uedgeC', - ['uedgeC_Forthon.c', - os.path.join(builddir, 'Forthon.c'), - 'com/handlers.c', 'com/vector.c','bbb/exmain.c'], - include_dirs=[builddir, numpy.get_include()], - library_dirs=library_dirs, - libraries=libraries, - define_macros=define_macros, - extra_objects=uedgeobjects, - extra_link_args=['-g','-DFORTHON'] + - fcompiler.extra_link_args, - extra_compile_args=fcompiler.extra_compile_args - )], - - cmdclass={'build': uedgeBuild, 'clean': uedgeClean}, - test_suite="pytests", - install_requires=['forthon'], - # note that include_dirs may have to be expanded in the line above - classifiers=['Programming Language :: Python', - 'Programming Language :: Python :: 3'] - - ) +setup( + ext_modules=[Extension('uedge.uedgeC', + ['uedgeC_Forthon.c', + os.path.join(builddir, 'Forthon.c'), + 'com/handlers.c', 'com/vector.c','bbb/exmain.c'], + include_dirs=[builddir, numpy.get_include()], + library_dirs=library_dirs, + libraries=libraries, + define_macros=define_macros, + extra_objects=uedgeobjects, + extra_link_args=['-g','-DFORTHON'] + + fcompiler.extra_link_args, + extra_compile_args=fcompiler.extra_compile_args + )], + cmdclass={ + 'build': uedgeBuild, + 'clean': uedgeClean, +# 'develop': CustomDevelopCommand, +# 'egg_info': CustomEggInfoCommand, + }, +# test_suite="pytests", +) diff --git a/pyscripts/Makefile.am b/src/uedge/Makefile.am similarity index 100% rename from pyscripts/Makefile.am rename to src/uedge/Makefile.am diff --git a/src/uedge/VERSION b/src/uedge/VERSION new file mode 100644 index 00000000..ac21f89b --- /dev/null +++ b/src/uedge/VERSION @@ -0,0 +1 @@ +8.1.0.0 diff --git a/src/uedge/__init__.py b/src/uedge/__init__.py new file mode 100755 index 00000000..a396f5eb --- /dev/null +++ b/src/uedge/__init__.py @@ -0,0 +1,25 @@ +from .uedge import * +from os import path +import uedge.checkver +from uedge import __path__ + +with open(path.join(__path__[0],"VERSION")) as f: + __version__ = f.read().replace('\n', '').strip() + +# Load the startup file .uedgerc.py from cwd or home. +# +_homefile = path.join(path.expanduser('~'), '.uedgerc.py') +_localfile = path.join(path.expanduser('.'), '.uedgerc.py') + +if path.exists(_localfile): + with open(_localfile) as f: + exec(open(_localfile).read()) +elif path.exists(_homefile): + with open(_homefile) as f: + exec(open(_homefile).read()) + +# +# Ensure that the UEDGE internal version matches the Python release +# + +uedge.bbb.uedge_ver = __version__ diff --git a/pyscripts/cdf4.py b/src/uedge/cdf4.py similarity index 100% rename from pyscripts/cdf4.py rename to src/uedge/cdf4.py diff --git a/src/uedge/checkver.py b/src/uedge/checkver.py new file mode 100644 index 00000000..ffd6a56d --- /dev/null +++ b/src/uedge/checkver.py @@ -0,0 +1,28 @@ +pkg = "uedge" + +try: + import json + import urllib.request + + try: + import importlib.metadata + + thisver = importlib.metadata.version(pkg) + except: + import pkg_resources + + thisver = pkg_resources.get_distribution(pkg).version + + contents = urllib.request.urlopen("https://pypi.org/pypi/" + pkg + "/json").read() + data = json.loads(contents.decode()) + thatver = data["info"]["version"] + + if thisver < thatver: + print() + print("Uedge version " + thisver + ", an update is available to " + thatver) + print() + +except Exception as err: + print() + print("Error checking pypi version: {}".format(err)) + print() diff --git a/pyscripts/convert1.py b/src/uedge/convert1.py similarity index 100% rename from pyscripts/convert1.py rename to src/uedge/convert1.py diff --git a/pyscripts/defaults.yaml b/src/uedge/defaults.yaml similarity index 100% rename from pyscripts/defaults.yaml rename to src/uedge/defaults.yaml diff --git a/src/uedge/filelists.py b/src/uedge/filelists.py new file mode 100755 index 00000000..b927408c --- /dev/null +++ b/src/uedge/filelists.py @@ -0,0 +1,17 @@ +# Methods to create a list of files in a directory, and a sub-list containing sspecified suffixes. + +import os +import string +def filelist(path): + return os.listdir(path) + +def filesublist(path,suffix): + sublist = [] + biglist = filelist(path) + for filename in biglist: + filesplit = filename.split(".") + if filesplit[-1] == suffix: + sublist.append(filename) + return sublist + + diff --git a/pyscripts/gridue.py b/src/uedge/gridue.py similarity index 100% rename from pyscripts/gridue.py rename to src/uedge/gridue.py diff --git a/pyscripts/hdf5.py b/src/uedge/hdf5.py similarity index 100% rename from pyscripts/hdf5.py rename to src/uedge/hdf5.py diff --git a/pyscripts/rundt.py b/src/uedge/rundt.py similarity index 98% rename from pyscripts/rundt.py rename to src/uedge/rundt.py index 38308d0d..1598cd32 100644 --- a/pyscripts/rundt.py +++ b/src/uedge/rundt.py @@ -891,13 +891,13 @@ def issuccess(): print('++++++++++++++++++++++++++++++++++++++++') print('Total runtime: {}'.format(timedelta( seconds=round(time()-self.tstart)))) - self.savesuccess('SUCCESS_{}.hdf5'.format(self.savedir)) + self.savesuccess('{}/SUCCESS.hdf5'.format(self.savedir)) self.restorevalues() return True else: if self.isave >= self.saveres: self.isave = 0 - self.savesuccess(self.savefname.format('{:.3f}'.format(self.lastsuccess).replace('.','p'))) + self.savesuccess(self.savefname.format('{:.3f}'.format(100*self.lastsuccess).replace('.','p'))) else: self.isave += 1 @@ -949,7 +949,7 @@ def staticiter(): bbb.sfscal[:bbb.neq])**2))**0.5 if bbb.dtreal > 1: bbb.dtreal = 1e20 - print('\n===== STATIC ITERATION AT DTREAL={:.2e} ====='.format(bbb.dtreal)) + print('\n===== STATIC ITERATION FOR DTREAL={:.2e} AT {:.1f}% ====='.format(bbb.dtreal, self.lastsuccess*100)) bbb.ftol = max(min(bbb.ftol, 0.01*fnorm_old), 1e-9) # Take a converging step if self.exmain_isaborted(): @@ -970,7 +970,7 @@ def staticiter(): print('\n===== STATIC FNRM REDUCTION FAILED =====\n') return False self.savesuccess(self.savefname.format('{:.3f}_staticiter'.format(\ - self.lastsuccess).replace('.','p') + 100*self.lastsuccess).replace('.','p') )) print('===== CONVERGED AT STEADY STATE: RETURNING TO MAIN LOOP =====') bbb.dtreal = dtreal_orig @@ -1000,7 +1000,7 @@ def dtsolve(dtdeltafac): # Ensure a first time-step can be taken dtdelta = self.lastsuccess + dtdeltafac/100 while bbb.iterm != 1: - dtdelta = self.lastsuccess + dtdeltafac/100 + dtdelta = min(self.lastsuccess + dtdeltafac/100, 1) setvar(dtdelta) if self.exmain_isaborted(): setvar(self.lastsuccess) @@ -1015,7 +1015,7 @@ def dtsolve(dtdeltafac): if abort is False: self.converge(dtreal=dtreal, savedir='.', savefname=self.savefname.format('{:.3f}_dtrun'.format(\ - dtdelta).replace('.','p')).replace('.hdf5',''), + dtdelta*100).replace('.','p')).replace('.hdf5',''), message='Solving for delta={:.3f}%'.format(dtdelta*100), ii1max=ii1max, **kwargs) if bbb.iterm == 1: @@ -1232,7 +1232,8 @@ def dtsolve(dtdeltafac): print('===== CONTINUATION SOLVE FAILED =====') print('=====================================') print('Last successful step for {}: {:.4e}'.format(\ - self.var, self.lastsuccess) + str(list(self.var.keys())).replace('[','').replace(']',''), + self.lastsuccess) ) return # Start trying to reset convergence @@ -1257,6 +1258,7 @@ def dtsolve(dtdeltafac): nstaticiter += 1 # Enter loop for time-dependent simulations if (bbb.iterm != 1) or (dtcall is True) or (nstaticiter==staticiter_max): + bbb.iterm = 0 print('===== ENTER TIME-DEPENDENT SOLVE =====') if dtsolve(dtdeltafac) is False: return diff --git a/pyscripts/sources.py b/src/uedge/sources.py similarity index 100% rename from pyscripts/sources.py rename to src/uedge/sources.py diff --git a/pyscripts/uedge.py b/src/uedge/uedge.py similarity index 100% rename from pyscripts/uedge.py rename to src/uedge/uedge.py diff --git a/pyscripts/uedge_lists.py b/src/uedge/uedge_lists.py similarity index 100% rename from pyscripts/uedge_lists.py rename to src/uedge/uedge_lists.py diff --git a/pyscripts/uedgeplots.py b/src/uedge/uedgeplots.py similarity index 100% rename from pyscripts/uedgeplots.py rename to src/uedge/uedgeplots.py