diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml
index bceb4107..1435fa9a 100644
--- a/.github/workflows/build-and-test.yml
+++ b/.github/workflows/build-and-test.yml
@@ -18,9 +18,11 @@ jobs:
uses: actions/checkout@v2
- name: Install fake precice
run: |
- mkdir -p precice
+ mkdir -p precice
echo "from setuptools import setup" >> precice/setup.py
echo "setup(name='pyprecice', version='2.0.2.1')" >> precice/setup.py
python3 -m pip install ./precice/
- name: Run unit tests
- run: python3 setup.py test
+ run: python3 setup.py test -s tests.unit
+ - name: Run integration tests
+ run: python3 setup.py test -s tests.integration
diff --git a/.github/workflows/check-pep8.yml b/.github/workflows/check-pep8.yml
new file mode 100644
index 00000000..cc74941b
--- /dev/null
+++ b/.github/workflows/check-pep8.yml
@@ -0,0 +1,15 @@
+name: autopep8
+on: push
+jobs:
+ autopep8:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: autopep8
+ id: autopep8
+ uses: peter-evans/autopep8@v1
+ with:
+ args: --recursive --diff --aggressive --aggressive --exit-code --ignore E402 --max-line-length 120 .
+ - name: Fail if autopep8 made changes
+ if: ${{ steps.autopep8.outputs.exit-code == 2 }}
+ run: exit 1
diff --git a/.github/workflows/run-tutorials.yml b/.github/workflows/run-tutorials.yml
new file mode 100644
index 00000000..2ac02790
--- /dev/null
+++ b/.github/workflows/run-tutorials.yml
@@ -0,0 +1,60 @@
+name: Run preCICE Tutorials
+on:
+ push:
+ branches:
+ - master
+ - develop
+ pull_request:
+ paths:
+ - '**'
+
+jobs:
+ run_ht_simple:
+ name: Run HT, simple
+ runs-on: ubuntu-latest
+ container: precice/precice
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@v2
+ - name: Install Dependencies & FEniCS
+ run: |
+ apt-get -qq update
+ apt-get -qq install software-properties-common python3-dev python3-pip git apt-utils
+ add-apt-repository -y ppa:fenics-packages/fenics
+ apt-get -qq install --no-install-recommends fenics
+ rm -rf /var/lib/apt/lists/*
+ - name: Install adapter
+ run: pip3 install --user .
+ - name: Fix broken FEniCS installation (see https://fenicsproject.discourse.group/t/installing-python-package-with-fenics-dependency-breaks-fenics-installation/4476)
+ run: pip3 uninstall -y fenics-ufl
+ - name: Get tutorials
+ run: git clone -b develop https://github.com/precice/tutorials.git
+ - name: Run tutorial
+ run: |
+ cd tutorials/partitioned-heat-conduction/fenics
+ python3 heat.py -d & python3 heat.py -n
+
+ run_ht_complex:
+ name: Run HT, complex
+ runs-on: ubuntu-latest
+ container: precice/precice
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@v2
+ - name: Install Dependencies & FEniCS
+ run: |
+ apt-get -qq update
+ apt-get -qq install software-properties-common python3-dev python3-pip git apt-utils
+ add-apt-repository -y ppa:fenics-packages/fenics
+ apt-get -qq install --no-install-recommends fenics
+ rm -rf /var/lib/apt/lists/*
+ - name: Install adapter
+ run: pip3 install --user .
+ - name: Fix broken FEniCS installation (see https://fenicsproject.discourse.group/t/installing-python-package-with-fenics-dependency-breaks-fenics-installation/4476)
+ run: pip3 uninstall -y fenics-ufl
+ - name: Get tutorials
+ run: git clone -b develop https://github.com/precice/tutorials.git
+ - name: Run tutorial
+ run: |
+ cd tutorials/partitioned-heat-conduction-complex/fenics
+ python3 heat.py -d -i complex & python3 heat.py -n -i complex
diff --git a/.travis.yml b/.travis.yml
index 13910de7..fcc56dad 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,9 @@
-matrix:
+matrix:
+ allow_failures:
+ - name: "Systemtests [failure allowed]"
include:
- os: linux
- name: "Systemtests"
+ name: "Systemtests [failure allowed]"
if: fork = false AND ( branch = master OR branch = develop )
python: "3.6"
env: PY=python3
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a554bea7..0528cb2d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
# FEniCS-preCICE adapter changelog
+## 1.1.0
+
+* Only warn during initialization, if duplicate boundary point is found for point sources.
+* Remove deprecated package `fenicsadapter`. Don't use `import fenicsadapter`. Please use `import fenicsprecice`. https://github.com/precice/fenics-adapter/pull/121
+
## 1.0.1
* Bugfix for PointSources https://github.com/precice/fenics-adapter/issues/109
diff --git a/README.md b/README.md
index b3025205..1a6dbb66 100644
--- a/README.md
+++ b/README.md
@@ -1,21 +1,24 @@
FEniCS-preCICE adapter
----------------------
-
-
-
-preCICE-adapter for the open source computing platform FEniCS
+
+
+
+
+
+
+
+
+
-_**Note:** This adapter is currently purely expermental and limited in functionality. If you are interested in using it or you want to contribute, feel free to contact us via the [preCICE mailing list](https://mailman.informatik.uni-stuttgart.de/mailman/listinfo/precice)._
+preCICE-adapter for the open source computing platform FEniCS
**currently only supports 2D simulations in FEniCS**
-This adapter was developed by [Benjamin Rüth](https://www5.in.tum.de/wiki/index.php/Benjamin_R%C3%BCth,_M.Sc._(hons)) 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](https://www.lunduniversity.lu.se/lucat/user/09d80f0367a060bcf2a22d7c22e5e504).
-
# Installing the package
## Using pip3 to install from PyPI
@@ -53,11 +56,18 @@ Single tests can be also be run. For example the test `test_vector_write` in the
python3 -m unittest tests.test_write_read.TestWriteandReadData.test_vector_write
```
-# Use the adapter
+### Troubleshooting
-Add ``from fenicsprecice import Adapter`` in your FEniCS code. Please refer to the examples in the [tutorials repository](https://github.com/precice/tutorials) for usage examples:
+**FEniCS is suddenly broken:** There are two known issues with preCICE, fenicsprecice and FEniCS:
-The adapter is configured via a `json` configuration file. For example configuration files and usage refer to the tutorials ([fenics-fenics](https://github.com/precice/tutorials/tree/master/HT/partitioned-heat/fenics-fenics)).
+* If you see `ImportError: cannot import name 'sub_forms_by_domain'` run `pip3 uninstall -y fenics-ufl`. For details, refer to [issue #103](https://github.com/precice/fenics-adapter/issues/103).
+* If you see `ModuleNotFoundError: No module named 'dolfin'` and have installed PETSc from source, refer to [this forum post](https://fenicsproject.discourse.group/t/modulenotfounderror-no-module-named-dolfin-if-petsc-dir-is-set/4407). Short version: Try to use the PETSc that comes with your system, if possible. Note that you can also [compile preCICE without PETSc](https://www.precice.org/installation-source-configuration.html), if necessary.
+
+If this does not help, you can contact us on [gitter](https://gitter.im/precice/lobby) or [open an issue](https://github.com/precice/fenics-adapter/issues/new).
+
+# Use the adapter
+
+Please refer to [our website](https://www.precice.org/adapter-fenics.html#how-can-i-use-my-own-solver-with-the-adapter-).
# Packaging
@@ -65,6 +75,8 @@ To create and install the `fenicsprecice` python package the following instructi
# Citing
+If you are using this adapter, please refer to the [citing information on the FEniCS adapter](https://www.precice.org/adapter-fenics.html#how-to-cite).
+
preCICE is an academic project, developed at the [Technical University of Munich](https://www5.in.tum.de/) and at the [University of Stuttgart](https://www.ipvs.uni-stuttgart.de/). If you use preCICE, please [cite us](https://www.precice.org/publications/):
*H.-J. Bungartz, F. Lindner, B. Gatzhammer, M. Mehl, K. Scheufele, A. Shukaev, and B. Uekermann: preCICE - A Fully Parallel Library for Multi-Physics Surface Coupling. Computers and Fluids, 141, 250–258, 2016.*
@@ -74,3 +86,12 @@ If you are using FEniCS, please also consider the information on https://fenicsp
# Disclaimer
This offering is not approved or endorsed by the FEniCS Project, producer and distributor of the FEniCS software via https://fenicsproject.org/.
+
+# Development history
+
+The initial version of this adapter was developed by [Benjamin Rodenberg](https://www.in.tum.de/i05/personen/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](https://www.lunduniversity.lu.se/lucat/user/09d80f0367a060bcf2a22d7c22e5e504).
+
+[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).
+
+[Ishaan Desai](https://www.ipvs.uni-stuttgart.de/institute/team/Desai/) improved the user interface and extended the adapter to also allow for parallel FEniCS computations.
+
diff --git a/docs/ReleaseGuide.md b/docs/ReleaseGuide.md
index 92d1357f..0ba27c62 100644
--- a/docs/ReleaseGuide.md
+++ b/docs/ReleaseGuide.md
@@ -1,22 +1,23 @@
## Guide to release new version of the FEniCS-preCICE adapter
-The developer who is releasing a new version of FEniCS-preCICE adapter is expected to follow this work flow
+Before starting this process make sure to check that all relevant changes are included in the `CHANGELOG.md`. The developer who is releasing a new version of FEniCS-preCICE adapter is expected to follow this workflow:
-1. If it does not already exist, create a release branch with the version number of the planned release. Use develop as base for the branch. `git checkout develop`; `git checkout -b release_vX.X.X`. Perform the following steps only on the release branch, if not indicated differently.
+1. If it does not already exist, create a release branch with the version number of the planned release. Use develop as base for the branch. `git checkout develop`; `git checkout -b fenics-adapter-vX.X.X`. Perform the following steps only on the release branch, if not indicated differently.
-2. [Open a Pull Request from the branch `release_vX.X.X` to `master`](https://github.com/precice/fenics-adapter/compare) named after the version (i.e. `Release v1.0.0`) and briefly describe the new features of the release in the PR description.
+2. [Open a Pull Request from the branch `fenics-adapter-vX.X.X` to `master`](https://github.com/precice/fenics-adapter/compare) named after the version (i.e. `Release v1.0.0`) and briefly describe the new features of the release in the PR description.
- a) Check `CHANGELOG.md`, if necessary, update `CHANGELOG.md` on `develop` and merge into `release_vX.X.X`
-
- b) Before merging the PR, make sure to bump the version in `CHANGELOG.md` on `release_vX.X.X`
+3. Bump the version in the following places:
-3. [Draft a New Release](https://github.com/precice/fenics-adapter/releases/new) in the `Releases` section of the repository page in a web browser. The release tag needs to be the exact version number (i.e.`v1.0.0` or `v1.0.0rc1`, compare to [existing tags](https://github.com/precice/fenics-adapter/tags)). Use `@target:master`. Release title is also the version number (i.e. `v1.0.0` or `v1.0.0rc1`, compare to [existing releases](https://github.com/precice/fenics-adapter/tags)).
-*Note:* If it is a pre-release then the option *This is a pre-release* needs to be selected at the bottom of the page. Use `@target:release_vX.X.X` for a pre-release, since we will never merge a pre-release into master.
+ a) Before merging the PR, make sure to bump the version in `CHANGELOG.md` on `fenics-adapter-vX.X.X`
+ b) There is no need to bump the version anywhere else, since we use the [python-versioneer](https://github.com/python-versioneer/python-versioneer/) for maintaining the version everywhere else.
+
+4. [Draft a New Release](https://github.com/precice/fenics-adapter/releases/new) in the `Releases` section of the repository page in a web browser. The release tag needs to be the exact version number (i.e.`v1.0.0` or `v1.0.0rc1`, compare to [existing tags](https://github.com/precice/fenics-adapter/tags)). Use `@target:master`. Release title is also the version number (i.e. `v1.0.0` or `v1.0.0rc1`, compare to [existing releases](https://github.com/precice/fenics-adapter/tags)).
+*Note:* If it is a pre-release then the option *This is a pre-release* needs to be selected at the bottom of the page. Use `@target:fenics-adapter-vX.X.X` for a pre-release, since we will never merge a pre-release into master.
a) If a pre-release is made: Directly hit the "Publish release" button in your Release Draft. Now you can check the artifacts (e.g. release on [PyPI](https://pypi.org/project/fenicsprecice/#history)) of the release. *Note:* As soon as a new tag is created github actions will take care of deploying the new version on PyPI using [this workflow](https://github.com/precice/fenics-adapter/actions?query=workflow%3A%22Upload+Python+Package%22).
- b) If this is a "real" release: As soon as one approving review is made, merge the release PR (`release_vX.X.X`) into `master`.
+ b) If this is a "real" release: As soon as one approving review is made, merge the release PR (`fenics-adapter-vX.X.X`) into `master`.
-4. Merge `master` into `develop` for synchronization of `develop`.
+5. Merge `master` into `develop` for synchronization of `develop`.
-5. If everything is in order up to this point then the new version can be released by hitting the "Publish release" button in your Release Draft.
+6. If everything is in order up to this point then the new version can be released by hitting the "Publish release" button in your Release Draft.
diff --git a/fenicsadapter/__init__.py b/fenicsadapter/__init__.py
deleted file mode 100644
index 49d2eb3a..00000000
--- a/fenicsadapter/__init__.py
+++ /dev/null
@@ -1,8 +0,0 @@
-import warnings
-warnings.warn("The package name fenicsadapter is deprecated. Please use fenicsprecice instead. Example: Use 'from fenicsprecice import Adapter', not 'from fenicsadapter import Adapter'. Using fenicsadapter will lead to an error in future releases.")
-
-# implemented following https://stackoverflow.com/a/24324577/5158031
-import sys
-import fenicsprecice
-
-sys.modules[__name__] = sys.modules['fenicsprecice']
diff --git a/fenicsprecice/adapter_core.py b/fenicsprecice/adapter_core.py
index d482a59e..81a52d98 100644
--- a/fenicsprecice/adapter_core.py
+++ b/fenicsprecice/adapter_core.py
@@ -32,6 +32,7 @@ class Vertices:
Vertices class provides a generic skeleton for vertices. A set of vertices has a set of global IDs, local IDs and
coordinates as defined in FEniCS.
"""
+
def __init__(self, vertex_type):
self._vertex_type = vertex_type
self._global_ids = None
@@ -91,12 +92,12 @@ def determine_function_type(input_obj):
tag : bool
0 if input_function is SCALAR and 1 if input_function is VECTOR.
"""
- if type(input_obj) == FunctionSpace: # scalar-valued functions have rank 0 is FEniCS
+ if isinstance(input_obj, FunctionSpace): # scalar-valued functions have rank 0 is FEniCS
if input_obj.num_sub_spaces() == 0:
return FunctionType.SCALAR
elif input_obj.num_sub_spaces() == 2:
return FunctionType.VECTOR
- elif type(input_obj) == Function:
+ elif isinstance(input_obj, Function):
if input_obj.value_rank() == 0:
return FunctionType.SCALAR
elif input_obj.value_rank() == 1:
@@ -107,7 +108,7 @@ def determine_function_type(input_obj):
raise Exception("Error determining type of given dolfin FunctionSpace")
-def filter_point_sources(point_sources, filter_out):
+def filter_point_sources(point_sources, filter_out, warn_duplicate=True):
"""
Filter dictionary of PointSources (point_sources) with respect to a given domain (filter_out). If a PointSource
is applied at a point inside of the given domain (filter_out), this PointSource will be removed from dictionary.
@@ -118,6 +119,8 @@ def filter_point_sources(point_sources, filter_out):
Dictionary containing coordinates and associated PointSources {(point_x, point_y): PointSource, ...}.
filter_out: FEniCS domain
Defines the domain where PointSources should be filtered out.
+ warn_duplicate: bool
+ Set False to surpress warnings, if double-boundary points are filtered out.
Returns
-------
@@ -128,10 +131,10 @@ def filter_point_sources(point_sources, filter_out):
for point in point_sources.keys():
# Filter double boundary points to avoid instabilities and create PointSource
- if filter_out.inside(point, 1):
- print("Found a double-boundary point at {location}.".format(location=point))
- else:
+ if not filter_out.inside(point, 1):
filtered_point_sources[point] = point_sources[point]
+ elif warn_duplicate:
+ logger.warning("Found a double-boundary point at {location}.".format(location=point))
return filtered_point_sources
@@ -153,7 +156,7 @@ def convert_fenics_to_precice(fenics_function, local_ids):
Array of FEniCS function values at each point on the boundary.
"""
- if type(fenics_function) is not Function:
+ if not isinstance(fenics_function, Function):
raise Exception("Cannot handle data type {}".format(type(fenics_function)))
precice_data = []
@@ -382,8 +385,8 @@ def get_forces_as_point_sources(fixed_boundary, function_space, data):
y_forces[key] = PointSource(function_space.sub(1), Point(px, py), nodal_data[i, 1])
# Avoid application of PointSource and Dirichlet boundary condition at the same point by filtering
- x_forces = filter_point_sources(x_forces, fixed_boundary)
- y_forces = filter_point_sources(y_forces, fixed_boundary)
+ x_forces = filter_point_sources(x_forces, fixed_boundary, warn_duplicate=False)
+ y_forces = filter_point_sources(y_forces, fixed_boundary, warn_duplicate=False)
return x_forces.values(), y_forces.values() # don't return dictionary, but list of PointSources
diff --git a/fenicsprecice/config.py b/fenicsprecice/config.py
index 0ac58076..9f1b7f37 100644
--- a/fenicsprecice/config.py
+++ b/fenicsprecice/config.py
@@ -13,6 +13,7 @@ class Config:
configuration file. Initializer calls read_json() method. Instance attributes
can be accessed by provided getter functions.
"""
+
def __init__(self, adapter_config_filename):
self._config_file_name = None
@@ -42,12 +43,12 @@ def read_json(self, adapter_config_filename):
try:
self._write_data_name = data["interface"]["write_data_name"]
- except:
+ except KeyError:
self._write_data_name = None # not required for one-way coupling, if this participant reads data
try:
self._read_data_name = data["interface"]["read_data_name"]
- except:
+ except KeyError:
self._read_data_name = None # not required for one-way coupling, if this participant writes data
read_file.close()
diff --git a/fenicsprecice/expression_core.py b/fenicsprecice/expression_core.py
index b794a013..08bf63cd 100644
--- a/fenicsprecice/expression_core.py
+++ b/fenicsprecice/expression_core.py
@@ -61,7 +61,8 @@ def update_boundary_data(self, vals, coords_x, coords_y=None, coords_z=None):
def interpolate(self, x):
# TODO: the correct way to deal with this would be using an abstract class. Since this is technically more
- # complex and the current implementation is a workaround anyway, we do not use the proper solution, but this hack.
+ # complex and the current implementation is a workaround anyway, we do not
+ # use the proper solution, but this hack.
"""
Interpolates at x. Uses buffered interpolant self._f.
Parameters
@@ -80,7 +81,8 @@ def interpolate(self, x):
def create_interpolant(self, x):
# TODO: the correct way to deal with this would be using an abstract class. Since this is technically more
- # complex and the current implementation is a workaround anyway, we do not use the proper solution, but this hack.
+ # complex and the current implementation is a workaround anyway, we do not
+ # use the proper solution, but this hack.
"""
Creates interpolant from boundary data that has been provided before.
@@ -168,12 +170,8 @@ class SegregatedRBFInterpolationExpression(CouplingExpression):
def segregated_interpolant_2d(self, coords_x, coords_y, data):
assert(coords_x.shape == coords_y.shape)
# create least squares system to approximate a * x ** 2 + b * x + c ~= y
- lstsq_interp = lambda x, y, w: w[0] * x ** 2 + \
- w[1] * y ** 2 + \
- w[2] * x * y + \
- w[3] * x + \
- w[4] * y + \
- w[5]
+
+ def lstsq_interp(x, y, w): return w[0] * x ** 2 + w[1] * y ** 2 + w[2] * x * y + w[3] * x + w[4] * y + w[5]
A = np.empty((coords_x.shape[0], 0))
n_unknowns = 6
diff --git a/fenicsprecice/fenicsprecice.py b/fenicsprecice/fenicsprecice.py
index 07c3f3c2..8574009f 100644
--- a/fenicsprecice/fenicsprecice.py
+++ b/fenicsprecice/fenicsprecice.py
@@ -8,7 +8,7 @@
import precice
from .adapter_core import FunctionType, determine_function_type, convert_fenics_to_precice, set_fenics_vertices, \
set_owned_vertices, set_unowned_vertices, get_coupling_boundary_edges, get_forces_as_point_sources, \
- get_communication_map, communicate_shared_vertices, CouplingMode, Vertices, VertexType
+ get_communication_map, communicate_shared_vertices, CouplingMode, Vertices, VertexType, filter_point_sources
from .expression_core import SegregatedRBFInterpolationExpression, EmptyExpression
from .solverstate import SolverState
from fenics import Function, FunctionSpace
@@ -112,21 +112,24 @@ def create_coupling_expression(self):
if not self._empty_rank:
try: # works with dolfin 1.6.0
- coupling_expression = self._my_expression(
- element=self._read_function_space.ufl_element()) # element information must be provided, else DOLFIN assumes scalar function
+ # element information must be provided, else DOLFIN assumes scalar function
+ coupling_expression = self._my_expression(element=self._read_function_space.ufl_element())
except (TypeError, KeyError): # works with dolfin 2017.2.0
coupling_expression = self._my_expression(element=self._read_function_space.ufl_element(), degree=0)
else:
try: # works with dolfin 1.6.0
- coupling_expression = EmptyExpression(
- element=self._read_function_space.ufl_element()) # element information must be provided, else DOLFIN assumes scalar function
+ # element information must be provided, else DOLFIN assumes scalar function
+ coupling_expression = EmptyExpression(element=self._read_function_space.ufl_element())
except (TypeError, KeyError): # works with dolfin 2017.2.0
coupling_expression = EmptyExpression(element=self._read_function_space.ufl_element(), degree=0)
if self._read_function_type == FunctionType.SCALAR:
- coupling_expression._vals = np.empty(
- shape=0) # todo: try to find a solution where we don't have to access the private member coupling_expression._vals
+ # todo: try to find a solution where we don't have to access the private
+ # member coupling_expression._vals
+ coupling_expression._vals = np.empty(shape=0)
elif self._read_function_type == FunctionType.VECTOR:
- coupling_expression._vals = np.empty(shape=(0, 0)) # todo: try to find a solution where we don't have to access the private member coupling_expression._vals
+ # todo: try to find a solution where we don't have to access the private
+ # member coupling_expression._vals
+ coupling_expression._vals = np.empty(shape=(0, 0))
coupling_expression.set_function_type(self._read_function_type)
@@ -281,10 +284,10 @@ def initialize(self, coupling_subdomain, read_function_space=None, write_object=
"""
write_function_space, write_function = None, None
- if type(write_object) is Function: # precice.initialize_data() will be called using this Function
+ if isinstance(write_object, Function): # precice.initialize_data() will be called using this Function
write_function_space = write_object.function_space()
write_function = write_object
- elif type(write_object) is FunctionSpace: # preCICE will use default zero values for initialization.
+ elif isinstance(write_object, FunctionSpace): # preCICE will use default zero values for initialization.
write_function_space = write_object
write_function = None
elif write_object is None:
@@ -293,7 +296,7 @@ def initialize(self, coupling_subdomain, read_function_space=None, write_object=
raise Exception("Given write object is neither of type dolfin.functions.function.Function or "
"dolfin.functions.functionspace.FunctionSpace")
- if type(read_function_space) is FunctionSpace:
+ if isinstance(read_function_space, FunctionSpace):
pass
elif read_function_space is None:
pass
@@ -340,9 +343,8 @@ def initialize(self, coupling_subdomain, read_function_space=None, write_object=
# Ensure that function spaces of read and write functions use the same mesh
if self._coupling_type is CouplingMode.BI_DIRECTIONAL_COUPLING:
- assert (self._read_function_space.mesh() is write_function_space.mesh()), "read_function_space and " \
- "write_object need to be " \
- "defined using the same mesh"
+ assert (self._read_function_space.mesh() is write_function_space.mesh()
+ ), "read_function_space and write_object need to be defined using the same mesh"
if fixed_boundary:
self._Dirichlet_Boundary = fixed_boundary
@@ -374,8 +376,14 @@ def initialize(self, coupling_subdomain, read_function_space=None, write_object=
self._send_map, self._recv_map = get_communication_map(self._comm, self._rank, self._read_function_space,
self._owned_vertices, self._unowned_vertices)
- # # Set mesh edges in preCICE to allow nearest-projection mapping
- # # Define a mapping between coupling vertices and their IDs in preCICE
+ # Check for double boundary points
+ if fixed_boundary:
+ # create empty data for the sake of searching for duplicate points
+ point_data = {tuple(key): None for key in self._owned_vertices.get_coordinates()}
+ _ = filter_point_sources(point_data, fixed_boundary, warn_duplicate=True)
+
+ # Set mesh edges in preCICE to allow nearest-projection mapping
+ # Define a mapping between coupling vertices and their IDs in preCICE
id_mapping = {key: value for key, value in zip(self._owned_vertices.get_global_ids(), self._precice_vertex_ids)}
edge_vertex_ids1, edge_vertex_ids2 = get_coupling_boundary_edges(function_space, coupling_subdomain,
diff --git a/setup.py b/setup.py
index 5498df3e..9ab8e585 100644
--- a/setup.py
+++ b/setup.py
@@ -3,9 +3,21 @@
import versioneer
# from https://stackoverflow.com/a/9079062
-import sys
+import sys
if sys.version_info[0] < 3:
- raise Exception("fenicsprecice only supports Python3. Did you run $python setup.py