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 ---------------------- - - Build status - GNU LGPL license -preCICE-adapter for the open source computing platform FEniCS + + Build and Test + + + Run preCICE Tutorials + + + Upload Python Package + -_**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