From 635074756a89e2807884ade44f194a7a3acf9bc2 Mon Sep 17 00:00:00 2001 From: Benjamin Rodenberg Date: Mon, 5 Aug 2024 11:37:16 +0200 Subject: [PATCH 01/11] Use `benjaminrodenberg/fenics` for CI stage "Build and Test" (#174) * Add dockerfile used for `benjaminrodenberg/fenics` * Use `pip install --break-system-packages ...`. --- .github/workflows/build-and-test.yml | 6 +++--- tools/testing/docker/Dockerfile | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 tools/testing/docker/Dockerfile diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index fcf01ee2..84a7c2d5 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -22,13 +22,13 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install setuptools wheel twine + pip3 install --break-system-packages setuptools wheel twine - name: Build distribution run: python3 setup.py sdist test: name: Run mock unit tests runs-on: ubuntu-latest - container: quay.io/fenicsproject/stable:current + container: benjaminrodenberg/fenics steps: - name: Checkout Repository uses: actions/checkout@v2 @@ -37,7 +37,7 @@ jobs: mkdir -p precice echo "from setuptools import setup" >> precice/setup.py echo "setup(name='pyprecice', version='3.0.0.0')" >> precice/setup.py - python3 -m pip install ./precice/ + pip3 install --break-system-packages ./precice/ - name: Run unit tests run: python3 setup.py test -s tests.unit - name: Run integration tests diff --git a/tools/testing/docker/Dockerfile b/tools/testing/docker/Dockerfile new file mode 100644 index 00000000..4b187a89 --- /dev/null +++ b/tools/testing/docker/Dockerfile @@ -0,0 +1,14 @@ +# Dockerfile to build a ubuntu image containing the installed Debian package of a release +FROM ubuntu:24.04 + +# Add the precice user to run test with mpi +RUN useradd -m -s /bin/bash precice +ENV PRECICE_USER=precice + +# Installing necessary dependencies +RUN apt-get -qq update && \ + apt-get -qq install software-properties-common && \ + add-apt-repository -y ppa:fenics-packages/fenics && \ + apt-get -qq update && \ + apt-get -qq install --no-install-recommends fenics python3-pip && \ + rm -rf /var/lib/apt/lists/* From 5e713b85ca7625edf79b412b962f98641470d489 Mon Sep 17 00:00:00 2001 From: Benjamin Rodenberg Date: Mon, 19 Aug 2024 17:50:58 +0200 Subject: [PATCH 02/11] Fix link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 568bc8fe..912d7590 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ To create and install the `fenicsprecice` python package the following instructi ## Development history -The initial version of this adapter was developed by [Benjamin Rodenberg](https://www.cs.cit.tum.de/sccs/personen/benjamin-rodenberg/) during his research stay at Lund University in the group for [Numerical Analysis](http://www.maths.lu.se/english/research/research-divisions/numerical-analysis/) in close collaboration with Peter Meisrimel. +The initial version of this adapter was developed by [Benjamin Rodenberg](https://www.cs.cit.tum.de/sccs/personen/benjamin-rodenberg/) during his research stay at Lund University in the group for [Numerical Analysis]([http://www.maths.lu.se/english/research/research-divisions/numerical-analysis/](https://www.maths.lu.se/forskning/forskningsavdelningar/numerisk-analys/forskning/)) in close collaboration with Peter Meisrimel. [Richard Hertrich](https://github.com/richahert) contributed the possibility to perform FSI simulations using the adapter in his [Bachelor thesis](https://mediatum.ub.tum.de/node?id=1520579). From f78286f0de55af966f34a8abae6b0e703cfb49e4 Mon Sep 17 00:00:00 2001 From: Benjamin Rodenberg Date: Mon, 19 Aug 2024 17:55:18 +0200 Subject: [PATCH 03/11] Fix link (typo in previous commit) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 912d7590..5f97135c 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ To create and install the `fenicsprecice` python package the following instructi ## Development history -The initial version of this adapter was developed by [Benjamin Rodenberg](https://www.cs.cit.tum.de/sccs/personen/benjamin-rodenberg/) during his research stay at Lund University in the group for [Numerical Analysis]([http://www.maths.lu.se/english/research/research-divisions/numerical-analysis/](https://www.maths.lu.se/forskning/forskningsavdelningar/numerisk-analys/forskning/)) in close collaboration with Peter Meisrimel. +The initial version of this adapter was developed by [Benjamin Rodenberg](https://www.cs.cit.tum.de/sccs/personen/benjamin-rodenberg/) during his research stay at Lund University in the group for [Numerical Analysis (Philipp Birken)](https://www.maths.lu.se/forskning/forskningsavdelningar/numerisk-analys/forskning/) in close collaboration with Peter Meisrimel. [Richard Hertrich](https://github.com/richahert) contributed the possibility to perform FSI simulations using the adapter in his [Bachelor thesis](https://mediatum.ub.tum.de/node?id=1520579). From 8e0dfa578fc41be31b381b546387ece938db589c Mon Sep 17 00:00:00 2001 From: Benjamin Rodenberg Date: Mon, 19 Aug 2024 18:02:39 +0200 Subject: [PATCH 04/11] Update setup.py (#175) * Fixes tests --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index d63a54c4..1b277b9e 100644 --- a/setup.py +++ b/setup.py @@ -39,6 +39,6 @@ author_email='info@precice.org', license='LGPL-3.0', packages=['fenicsprecice'], - install_requires=['pyprecice>=3.0.0.0', 'scipy', 'numpy>=1.13.3', 'mpi4py'], + install_requires=['pyprecice>=3.0.0.0', 'scipy', 'numpy>=1.13.3, <2', 'mpi4py'], test_suite='tests', zip_safe=False) From 98fcd95c9ffbfa8aa796ceb27a685b2875870eb4 Mon Sep 17 00:00:00 2001 From: NiklasV <139122850+NiklasVin@users.noreply.github.com> Date: Tue, 20 Aug 2024 10:19:17 +0200 Subject: [PATCH 05/11] Tests checking implementation of checkpointing/SolverState (#173) * Add tests to check if SolverState stores and returns the checkpointed state correctly --------- Co-authored-by: Benjamin Rodenberg --- CHANGELOG.md | 4 ++ tests/unit/test_checkpointing.py | 97 ++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 tests/unit/test_checkpointing.py diff --git a/CHANGELOG.md b/CHANGELOG.md index d420d9aa..c5f64a12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # FEniCS-preCICE adapter changelog +## latest + +* Add unit tests for checkpointing. [#173](https://github.com/precice/fenics-adapter/pull/173) + ## 2.1.0 * Additionally support checkpoints being provided as a list or tuple (of FEniCS Functions). [#170](https://github.com/precice/fenics-adapter/pull/170) diff --git a/tests/unit/test_checkpointing.py b/tests/unit/test_checkpointing.py new file mode 100644 index 00000000..b0ce63d1 --- /dev/null +++ b/tests/unit/test_checkpointing.py @@ -0,0 +1,97 @@ +from unittest.mock import MagicMock +from unittest import TestCase +from fenics import FunctionSpace, UnitSquareMesh, Expression, interpolate +from fenicsprecice.solverstate import SolverState + + +class TestCheckpointing(TestCase): + def test_solverstate_basic(self): + """ + Check if correct values are read from the checkpoint, while the state of the object that is copied is not changed + """ + n = 1 + size = 5 + mesh = UnitSquareMesh(size,size) + V = FunctionSpace(mesh, 'P', 2) + dummy_value = 1 + E = Expression("t", t=dummy_value, degree=2) + u = interpolate(E, V) + + # "write checkpoint" + sstate = SolverState(u, dummy_value, n) + # "read checkpoint" + u_cp, t_cp, n_cp = sstate.get_state() + + #check values + self.assertEqual(t_cp, dummy_value) + self.assertEqual(n, n_cp) + #function should be the same everywhere (-> check vector values of the function) + vec_u = u.vector() + vec_u_cp = u_cp.vector() + for i in range(size*size): + self.assertAlmostEqual(vec_u[i], vec_u_cp[i]) + + def test_solverstate_modification_vector(self): + """ + Check if correct values are read from the checkpoint, if the dof vector of the dolfin functions are changed directly + + Motivation for this test: Related to https://github.com/precice/fenics-adapter/pull/172 and https://github.com/precice/tutorials/pull/554 + """ + n = 1 + size = 5 + mesh = UnitSquareMesh(size,size) + V = FunctionSpace(mesh, 'P', 2) + ref_value = 1 + E = Expression("t", t=ref_value, degree=2) + u = interpolate(E, V) + + # "write checkpoint" + sstate = SolverState(u, ref_value, n) + + # modify state of u + dummy_value = ref_value + 2 + u.vector()[:] = dummy_value + + # "read checkpoint" + u_cp, _, _ = sstate.get_state() + + #check values + #function should be the same everywhere + #(so the vector values should all be ref_value) + vec_u_cp = u_cp.vector() + for i in range(size*size): + self.assertAlmostEqual(ref_value, vec_u_cp[i]) + + + def test_solverstate_modification_assign(self): + """ + Check if correct values are read from the checkpoint, if the dof of the dolfin functions are changed with the assign function + and not directly via the dof vector + """ + n = 1 + size = 5 + mesh = UnitSquareMesh(size,size) + V = FunctionSpace(mesh, 'P', 2) + ref_value = 1 + E = Expression("t", t=ref_value, degree=2) + u = interpolate(E, V) + + # "write checkpoint" + sstate = SolverState(u, ref_value, n) + + # modify state of u + # "compute" new solution + dummy_value = ref_value + 2 + E.t = dummy_value + u2 = interpolate(E,V) + u.assign(u2) + + # "read checkpoint" + u_cp, _, _ = sstate.get_state() + + #check values + #function should be the same everywhere + #(so the vector values should all be ref_value) + vec_u_cp = u_cp.vector() + for i in range(size*size): + self.assertAlmostEqual(ref_value, vec_u_cp[i]) From b04e6c9c628c92a5f97c62e1e9ed676206f05edf Mon Sep 17 00:00:00 2001 From: Benjamin Rodenberg Date: Tue, 20 Aug 2024 10:43:46 +0200 Subject: [PATCH 06/11] Fix autopep8. --- tests/unit/test_checkpointing.py | 33 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/tests/unit/test_checkpointing.py b/tests/unit/test_checkpointing.py index b0ce63d1..594e2990 100644 --- a/tests/unit/test_checkpointing.py +++ b/tests/unit/test_checkpointing.py @@ -11,7 +11,7 @@ def test_solverstate_basic(self): """ n = 1 size = 5 - mesh = UnitSquareMesh(size,size) + mesh = UnitSquareMesh(size, size) V = FunctionSpace(mesh, 'P', 2) dummy_value = 1 E = Expression("t", t=dummy_value, degree=2) @@ -22,24 +22,24 @@ def test_solverstate_basic(self): # "read checkpoint" u_cp, t_cp, n_cp = sstate.get_state() - #check values + # check values self.assertEqual(t_cp, dummy_value) self.assertEqual(n, n_cp) - #function should be the same everywhere (-> check vector values of the function) + # function should be the same everywhere (-> check vector values of the function) vec_u = u.vector() vec_u_cp = u_cp.vector() - for i in range(size*size): + for i in range(size * size): self.assertAlmostEqual(vec_u[i], vec_u_cp[i]) def test_solverstate_modification_vector(self): """ - Check if correct values are read from the checkpoint, if the dof vector of the dolfin functions are changed directly + Check if correct values are read from the checkpoint, if the dof vector of the dolfin functions are changed directly Motivation for this test: Related to https://github.com/precice/fenics-adapter/pull/172 and https://github.com/precice/tutorials/pull/554 """ n = 1 size = 5 - mesh = UnitSquareMesh(size,size) + mesh = UnitSquareMesh(size, size) V = FunctionSpace(mesh, 'P', 2) ref_value = 1 E = Expression("t", t=ref_value, degree=2) @@ -55,13 +55,12 @@ def test_solverstate_modification_vector(self): # "read checkpoint" u_cp, _, _ = sstate.get_state() - #check values - #function should be the same everywhere - #(so the vector values should all be ref_value) + # check values + # function should be the same everywhere + # (so the vector values should all be ref_value) vec_u_cp = u_cp.vector() - for i in range(size*size): + for i in range(size * size): self.assertAlmostEqual(ref_value, vec_u_cp[i]) - def test_solverstate_modification_assign(self): """ @@ -70,7 +69,7 @@ def test_solverstate_modification_assign(self): """ n = 1 size = 5 - mesh = UnitSquareMesh(size,size) + mesh = UnitSquareMesh(size, size) V = FunctionSpace(mesh, 'P', 2) ref_value = 1 E = Expression("t", t=ref_value, degree=2) @@ -83,15 +82,15 @@ def test_solverstate_modification_assign(self): # "compute" new solution dummy_value = ref_value + 2 E.t = dummy_value - u2 = interpolate(E,V) + u2 = interpolate(E, V) u.assign(u2) # "read checkpoint" u_cp, _, _ = sstate.get_state() - #check values - #function should be the same everywhere - #(so the vector values should all be ref_value) + # check values + # function should be the same everywhere + # (so the vector values should all be ref_value) vec_u_cp = u_cp.vector() - for i in range(size*size): + for i in range(size * size): self.assertAlmostEqual(ref_value, vec_u_cp[i]) From 8716694dd87067702547b574a7739c7e70303bd9 Mon Sep 17 00:00:00 2001 From: Benjamin Rodenberg Date: Fri, 23 Aug 2024 15:40:05 +0200 Subject: [PATCH 07/11] Use `copy(deepcopy=true)` for checkpointing (#172) --- CHANGELOG.md | 1 + fenicsprecice/solverstate.py | 12 ++++++------ tests/integration/test_fenicsprecice.py | 6 +++++- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5f64a12..1ad96d2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## latest +* Use `copy(deepcopy=True)` when checkpointing to make checkpointing more user-friendly and secure. IMPORTANT: might increase runtime, please open an issue if you face serious problems. [#172](https://github.com/precice/fenics-adapter/pull/172) * Add unit tests for checkpointing. [#173](https://github.com/precice/fenics-adapter/pull/173) ## 2.1.0 diff --git a/fenicsprecice/solverstate.py b/fenicsprecice/solverstate.py index ca90a96f..1370080a 100644 --- a/fenicsprecice/solverstate.py +++ b/fenicsprecice/solverstate.py @@ -13,9 +13,9 @@ def __init__(self, payload, t, n): Iteration number. """ try: - self.payload = payload.copy() - except AttributeError: # if .copy() does not exist, it probably is a list - self.payload = [item.copy() for item in payload] + self.payload = payload.copy(deepcopy=True) + except (AttributeError, TypeError): # AttributeError, if .copy() does not exist; TypeError, if .copy(deepcopy) does not exist. -> Probably a list + self.payload = [item.copy(deepcopy=True) for item in payload] self.t = t self.n = n @@ -34,9 +34,9 @@ def get_state(self): Iteration number. """ try: - return self.payload.copy(), self.t, self.n - except AttributeError: # if .copy() does not exist, it probably is a list - return [item.copy() for item in self.payload], self.t, self.n + return self.payload.copy(deepcopy=True), self.t, self.n + except (AttributeError, TypeError): # AttributeError, if .copy() does not exist; TypeError, if .copy(deepcopy) does not exist. -> Probably a list + return [item.copy(deepcopy=True) for item in self.payload], self.t, self.n def print_state(self): payload, t, n = self.get_state() diff --git a/tests/integration/test_fenicsprecice.py b/tests/integration/test_fenicsprecice.py index faec6038..5bca1e22 100644 --- a/tests/integration/test_fenicsprecice.py +++ b/tests/integration/test_fenicsprecice.py @@ -25,7 +25,11 @@ def assign(self, new_value): """ self.value = new_value.value - def copy(self): + def copy(self, deepcopy=False): + """ + mock of dolfin.Function.copy + :param deepcopy: has no effect but we need to provide it to avoid throwing TypeError if copy(deepcopy=True) is called + """ returned_array = MockedArray() returned_array.value = self.value return returned_array From 2d1894b5fe84df1580c24f5b1974d420178c1f40 Mon Sep 17 00:00:00 2001 From: Benjamin Rodenberg Date: Thu, 5 Sep 2024 10:30:40 +0200 Subject: [PATCH 08/11] Add changelog entry. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ad96d2c..1a63ecff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Use `copy(deepcopy=True)` when checkpointing to make checkpointing more user-friendly and secure. IMPORTANT: might increase runtime, please open an issue if you face serious problems. [#172](https://github.com/precice/fenics-adapter/pull/172) * Add unit tests for checkpointing. [#173](https://github.com/precice/fenics-adapter/pull/173) +* Remove checks for FEniCS installation and python3 from `setup.py` since the approach is deprecated. [#182](https://github.com/precice/fenics-adapter/pull/182) ## 2.1.0 From b3a9a280cb840aa91d6fa005adbb0a40f159e27f Mon Sep 17 00:00:00 2001 From: Benjamin Rodenberg Date: Thu, 5 Sep 2024 11:40:44 +0200 Subject: [PATCH 09/11] Remove checks for FEniCS and python3 (#182) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Frédéric Simonis --- setup.py | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/setup.py b/setup.py index 1b277b9e..1f6d7126 100644 --- a/setup.py +++ b/setup.py @@ -1,29 +1,6 @@ import os from setuptools import setup import versioneer -import warnings - -# from https://stackoverflow.com/a/9079062 -import sys -if sys.version_info[0] < 3: - raise Exception("fenicsprecice only supports Python3. Did you run $python setup.py