Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

backports of #845 & #849 #850

Merged
merged 9 commits into from
Jan 29, 2024
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Install dependencies
run: python3 -m pip install flit
- name: Build package
Expand Down
54 changes: 29 additions & 25 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ env:
jobs:
build-python-package:
name: Build Python package
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
outputs:
wheel: ${{ steps.build.outputs.wheel }}
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Install build dependencies
run: python3 -m pip install flit
- name: Build package
Expand All @@ -30,7 +30,7 @@ jobs:
python3 -m flit build
echo wheel=`echo dist/*.whl` >> $GITHUB_OUTPUT
- name: Upload package artifacts
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: python-package
path: dist/
Expand All @@ -42,20 +42,22 @@ jobs:
strategy:
matrix:
include:
- {name: "baseline", os: ubuntu-latest, python-version: "3.10", matrix-backend: numpy, nprocs: 1}
- {name: "windows", os: windows-latest, python-version: "3.10", matrix-backend: numpy, nprocs: 1}
- {name: "macos", os: macos-latest, python-version: "3.10", matrix-backend: numpy, nprocs: 1}
- {name: "baseline", os: ubuntu-latest, python-version: "3.12", matrix-backend: numpy, nprocs: 1}
- {name: "windows", os: windows-latest, python-version: "3.12", matrix-backend: numpy, nprocs: 1}
- {name: "macos", os: macos-latest, python-version: "3.12", matrix-backend: numpy, nprocs: 1}
- {name: "python 3.7", os: ubuntu-latest, python-version: "3.7", matrix-backend: numpy, nprocs: 1}
- {name: "python 3.8", os: ubuntu-latest, python-version: "3.8", matrix-backend: numpy, nprocs: 1}
- {name: "python 3.9", os: ubuntu-latest, python-version: "3.9", matrix-backend: numpy, nprocs: 1}
- {name: "scipy matrix", os: ubuntu-latest, python-version: "3.10", matrix-backend: scipy, nprocs: 1}
- {name: "mkl linux", os: ubuntu-latest, python-version: "3.10", matrix-backend: mkl, nprocs: 1}
- {name: "mkl linux parallel", os: ubuntu-latest, python-version: "3.10", matrix-backend: mkl, nprocs: 2}
- {name: "mkl windows", os: windows-latest, python-version: "3.10", matrix-backend: mkl, nprocs: 1}
- {name: "mkl macos", os: macos-latest, python-version: "3.10", matrix-backend: mkl, nprocs: 1}
- {name: "parallel", os: ubuntu-latest, python-version: "3.10", matrix-backend: numpy, nprocs: 2}
- {name: "python 3.10", os: ubuntu-latest, python-version: "3.10", matrix-backend: numpy, nprocs: 1}
- {name: "python 3.11", os: ubuntu-latest, python-version: "3.11", matrix-backend: numpy, nprocs: 1}
- {name: "scipy matrix", os: ubuntu-latest, python-version: "3.12", matrix-backend: scipy, nprocs: 1}
- {name: "mkl linux", os: ubuntu-latest, python-version: "3.12", matrix-backend: mkl, nprocs: 1}
- {name: "mkl linux parallel", os: ubuntu-latest, python-version: "3.12", matrix-backend: mkl, nprocs: 2}
- {name: "mkl windows", os: windows-latest, python-version: "3.12", matrix-backend: mkl, nprocs: 1}
- {name: "mkl macos", os: macos-latest, python-version: "3.12", matrix-backend: mkl, nprocs: 1}
- {name: "parallel", os: ubuntu-latest, python-version: "3.12", matrix-backend: numpy, nprocs: 2}
- {name: "numpy 1.17", os: ubuntu-latest, python-version: "3.7", matrix-backend: numpy, nprocs: 1, numpy-version: ==1.17}
- {name: "tensorial", os: ubuntu-latest, python-version: "3.10", matrix-backend: numpy, nprocs: 1, tensorial: test}
- {name: "tensorial", os: ubuntu-latest, python-version: "3.12", matrix-backend: numpy, nprocs: 1, tensorial: test}
fail-fast: false
env:
_wheel: ${{ needs.build-python-package.outputs.wheel }}
Expand All @@ -70,15 +72,15 @@ jobs:
NUTILS_TENSORIAL: ${{ matrix.tensorial }}
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Move nutils directory
run: mv nutils _nutils
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Download Python package artifact
uses: actions/download-artifact@v2
uses: actions/download-artifact@v4
with:
name: python-package
path: dist/
Expand Down Expand Up @@ -107,7 +109,7 @@ jobs:
- name: Post-process coverage
run: python -um devtools.gha.coverage_report_xml
- name: Upload coverage
uses: codecov/codecov-action@v1
uses: codecov/codecov-action@v3
test-examples:
needs: build-python-package
name: 'Test examples ${{ matrix.os }}'
Expand All @@ -126,13 +128,15 @@ jobs:
PYTHONHASHSEED: 0
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Move nutils directory
run: mv nutils _nutils
- name: Set up Python
uses: actions/setup-python@v1
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Download Python package artifact
uses: actions/download-artifact@v2
uses: actions/download-artifact@v4
with:
name: python-package
path: dist/
Expand All @@ -146,10 +150,10 @@ jobs:
run: python -um unittest discover -b -q -t . -s examples
test-sphinx:
name: Test building docs
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Install dependencies
run: |
python3 -um pip install setuptools wheel
Expand All @@ -159,16 +163,16 @@ jobs:
build-and-test-container-image:
name: Build container image
needs: build-python-package
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
env:
# Fixes https://github.com/actions/virtual-environments/issues/3080
STORAGE_OPTS: overlay.mount_program=/usr/bin/fuse-overlayfs
_wheel: ${{ needs.build-python-package.outputs.wheel }}
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Download Python package artifact
uses: actions/download-artifact@v2
uses: actions/download-artifact@v4
with:
name: python-package
path: dist/
Expand Down
2 changes: 1 addition & 1 deletion examples/cahnhilliard.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def main(size: Length = parse('10cm'),
energy:

E(φ) := ∫_Ω ψ(φ) σ / ε + ∫_Ω .5 σ ε ‖∇φ‖² + ∫_Γ (σm + φ σd)
\ \ \
mixing energy interface energy wall energy

Proof: the time derivative of `E` followed by substitution of the strong form
Expand Down
24 changes: 12 additions & 12 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ readme = "README.md"
authors = [
{ name = "Evalf", email = "[email protected]" },
]
requires-python = '~=3.7'
requires-python = '>=3.7'
dependencies = [
"appdirs~=1.0",
"bottombar~=2.0.2",
"numpy>=1.17",
"nutils-poly~=1.0",
"psutil~=5.0",
"appdirs >=1,<2",
"bottombar >=2,<3",
"numpy >=1.17,<2",
"nutils-poly >=1,<2",
"psutil >=5,<6",
"stringly",
"treelog>=1.0b5",
"treelog >=1,<2",
]
dynamic = ["description", "version"]
classifiers = [
Expand All @@ -22,11 +22,11 @@ classifiers = [
]

[project.optional-dependencies]
docs = ["Sphinx>=1.8"]
export_mpl = ["matplotlib>=1.3", "pillow>2.6"]
matrix_mkl = ["mkl<2024"]
matrix_scipy = ["scipy>=0.13"]
import_gmsh = ["meshio"]
docs = ["Sphinx >=1.8,<8"]
export_mpl = ["matplotlib >=3.3,<4"]
matrix_mkl = ["mkl <2024"]
matrix_scipy = ["scipy >=0.13,<2"]
import_gmsh = ["meshio >=4,<6"]

[build-system]
requires = ["flit_core >=3.2,<4"]
Expand Down
20 changes: 10 additions & 10 deletions tests/test_expression_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -560,28 +560,28 @@ def test_define_for_3d(self):
def test_add_single_field(self):
ns = expression_v2.Namespace()
ns.add_field('u', numpy.array([1,2,3]))
self.assertEquals(ns.u.argshapes, dict(u=(3,)))
self.assertEquals(ns.u.shape, ())
self.assertEqual(ns.u.argshapes, dict(u=(3,)))
self.assertEqual(ns.u.shape, ())

def test_add_multiple_fields(self):
ns = expression_v2.Namespace()
ns.add_field(('u', 'v'), numpy.array([1,2,3]))
self.assertEquals(ns.u.argshapes, dict(u=(3,)))
self.assertEquals(ns.u.shape, ())
self.assertEquals(ns.v.argshapes, dict(v=(3,)))
self.assertEquals(ns.v.shape, ())
self.assertEqual(ns.u.argshapes, dict(u=(3,)))
self.assertEqual(ns.u.shape, ())
self.assertEqual(ns.v.argshapes, dict(v=(3,)))
self.assertEqual(ns.v.shape, ())

def test_add_single_field_multiple_bases(self):
ns = expression_v2.Namespace()
ns.add_field('u', numpy.array([1,2,3]), numpy.array([4,5,6,7]))
self.assertEquals(ns.u.argshapes, dict(u=(3,4)))
self.assertEquals(ns.u.shape, ())
self.assertEqual(ns.u.argshapes, dict(u=(3,4)))
self.assertEqual(ns.u.shape, ())

def test_add_single_field_with_shape(self):
ns = expression_v2.Namespace()
ns.add_field('u', numpy.array([1,2,3]), shape=(2,))
self.assertEquals(ns.u.argshapes, dict(u=(3,2)))
self.assertEquals(ns.u.shape, (2,))
self.assertEqual(ns.u.argshapes, dict(u=(3,2)))
self.assertEqual(ns.u.shape, (2,))

def test_copy(self):
ns1 = expression_v2.Namespace()
Expand Down
8 changes: 4 additions & 4 deletions tests/test_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def test_cast_invalid_argument(self):
function.Array.cast('132')

def test_cast_different_shapes(self):
with self.assertRaisesRegex(ValueError, 'cannot convert \[\[1, 2, 3\], \[4, 5\]\] to Array: all input arrays must have the same shape'):
with self.assertRaisesRegex(ValueError, 'cannot convert \\[\\[1, 2, 3\\], \\[4, 5\\]\\] to Array: all input arrays must have the same shape'):
function.Array.cast([[1,2,3],[4,5]])

def test_ndim(self):
Expand Down Expand Up @@ -53,11 +53,11 @@ def test_iter_known(self):
self.assertEqual(b.as_evaluable_array.eval(), 2)

def test_binop_notimplemented(self):
with self.assertRaisesRegex(TypeError, '^operand type\(s\) all returned NotImplemented from __array_ufunc__'):
with self.assertRaisesRegex(TypeError, '^operand type\\(s\\) all returned NotImplemented from __array_ufunc__'):
function.Argument('a', ()) + '1'

def test_rbinop_notimplemented(self):
with self.assertRaisesRegex(TypeError, '^operand type\(s\) all returned NotImplemented from __array_ufunc__'):
with self.assertRaisesRegex(TypeError, '^operand type\\(s\\) all returned NotImplemented from __array_ufunc__'):
'1' + function.Argument('a', ())

def test_deprecated_simplified(self):
Expand All @@ -76,7 +76,7 @@ def test_index(self):
self.assertEqual(function.Array.cast(2).__index__(), 2)
with self.assertRaisesRegex(ValueError, "cannot convert non-constant array to index: arguments=foo"):
function.Argument('foo', shape=(), dtype=int).__index__()
with self.assertRaisesRegex(ValueError, "cannot convert non-scalar array to index: shape=\(2,\)"):
with self.assertRaisesRegex(ValueError, "cannot convert non-scalar array to index: shape=\\(2,\\)"):
function.Array.cast([2, 3]).__index__()
with self.assertRaisesRegex(ValueError, "cannot convert non-integer array to index: dtype=float"):
function.Array.cast(2.5).__index__()
Expand Down
10 changes: 5 additions & 5 deletions tests/test_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ def _test_recursion_cache(testcase, solver_iter):
with testcase.assertLogs('nutils', 'DEBUG') as cm:
v = read(length)
testcase.assertEqual(v, reference[:length])
testcase.assertRegex('\n'.join(cm.output), '\[cache\.Recursion [0-9a-f]{40}\] start iterating')
testcase.assertRegex('\n'.join(cm.output), '\[cache\.Recursion [0-9a-f]{40}\.0000\] load' if i and max(lengths[:i]) > 0
else '\[cache\.Recursion [0-9a-f]{40}\.0000\] cache exhausted')
testcase.assertRegex('\n'.join(cm.output), '\\[cache\\.Recursion [0-9a-f]{40}\\] start iterating')
testcase.assertRegex('\n'.join(cm.output), '\\[cache\\.Recursion [0-9a-f]{40}\\.0000\\] load' if i and max(lengths[:i]) > 0
else '\\[cache\\.Recursion [0-9a-f]{40}\\.0000\\] cache exhausted')


def _test_solve_cache(testcase, solver_gen):
Expand All @@ -46,10 +46,10 @@ def _test_solve_cache(testcase, solver_gen):
with testcase.assertLogs('nutils', 'DEBUG') as cm:
v2, info = _edit(solver_gen().solve_withinfo(1e-5))
testcase.assertEqual(v1, v2)
testcase.assertRegex('\n'.join(cm.output), '\[cache\.function [0-9a-f]{40}\] load')
testcase.assertRegex('\n'.join(cm.output), '\\[cache\\.function [0-9a-f]{40}\\] load')
with testcase.assertLogs('nutils', 'DEBUG') as cm:
solver_gen().solve(1e-6)
testcase.assertRegex('\n'.join(cm.output), '\[cache\.function [0-9a-f]{40}\] failed to load')
testcase.assertRegex('\n'.join(cm.output), '\\[cache\\.function [0-9a-f]{40}\\] failed to load')


class laplace(TestCase):
Expand Down