From 513e3de1713b747e0bc6162db831d5c8fcff22e2 Mon Sep 17 00:00:00 2001 From: Gerasimos Chourdakis Date: Tue, 8 Feb 2022 19:32:19 +0100 Subject: [PATCH 01/31] Switch to unreleased version --- Adapter.C | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Adapter.C b/Adapter.C index 1d6ef3e9..e4da2dca 100644 --- a/Adapter.C +++ b/Adapter.C @@ -10,7 +10,7 @@ preciceAdapter::Adapter::Adapter(const Time& runTime, const fvMesh& mesh) : runTime_(runTime), mesh_(mesh) { - adapterInfo("Loaded the OpenFOAM-preCICE adapter - v1.1.0.", "info"); + adapterInfo("Loaded the OpenFOAM-preCICE adapter - v1.1.0 + unreleased changes.", "info"); return; } From 888c0ba3dccaf6bb7dc61126fcb5b2fc8d7249bc Mon Sep 17 00:00:00 2001 From: Gerasimos Chourdakis Date: Tue, 8 Feb 2022 23:37:33 +0100 Subject: [PATCH 02/31] Update release pull request template after v1.1.0. --- tools/release_pull_request_template.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/release_pull_request_template.md b/tools/release_pull_request_template.md index acbce4f5..cd604177 100644 --- a/tools/release_pull_request_template.md +++ b/tools/release_pull_request_template.md @@ -45,6 +45,8 @@ master <-- OpenFOAM4 <-- OpenFOAM5 <-- OpenFOAM6 <-- OpenFOAM7 <-- OpenFOAM8 <-- - [ ] Copy all the changelog entries into `CHANGELOG.md` - [ ] Delete `changelog-entries/` +- [ ] Mark issues and pull requests that made it to this milestone. +- [ ] Collect a list of contributors to acknowledge (particularly non-code contributions that are not easily visible on GitHub). - [ ] Draft and discuss release notes ## Bump the version @@ -52,6 +54,7 @@ master <-- OpenFOAM4 <-- OpenFOAM5 <-- OpenFOAM6 <-- OpenFOAM7 <-- OpenFOAM8 <-- - [ ] Decide on the version using the versioning strategy documented in the user docs (see page "Get the OpenFOAM adapter") - [ ] Bump the version in `CHANGELOG.md` - [ ] Bump the version in `Adapter.C` (removing the `+ unreleased changes` part). +- [ ] Make the version bump commit the last commit before merging. ## Merge @@ -62,7 +65,7 @@ master <-- OpenFOAM4 <-- OpenFOAM5 <-- OpenFOAM6 <-- OpenFOAM7 <-- OpenFOAM8 <-- ## Release - [ ] Create a Release on GitHub -- [ ] Download an archive of the repository (i.e., no `.git/` or `.gitignore`) for each version and attach to the release +- [ ] Download an archive of the repository (i.e., no `.git/` or `.gitignore`) for each version and attach to the release. Use the link `https://github.com/precice/openfoam-adapter/archive/refs/heads/BRANCH.tar.gz` (substitute `BRANCH`). Rename the folder in each archive to reflect the name of the archive. - branch `master`: archive `openfoam-adapter_v1.0.0_OpenFOAMv1812-v2112.tar.gz` (adjust `v2112` to the latest supported, and `v1.0.0` to the actual version) - branch `OpenFOAM4`: archive `openfoam-adapter_v1.0.0_OpenFOAM4_5_v1806.tar.gz` - branch `OpenFOAM6`: archive `openfoam-adapter_v1.0.0_OpenFOAM6_experimental.tar.gz` @@ -76,6 +79,7 @@ master <-- OpenFOAM4 <-- OpenFOAM5 <-- OpenFOAM6 <-- OpenFOAM7 <-- OpenFOAM8 <-- - [ ] Update the git module on the website - [ ] Update workflows in the tutorials repository, if needed (e.g., OpenFOAM version) - [ ] Update external documentation (tutorials, website), e.g., regarding the adapter or OpenFOAM version. + - [ ] Quickstart - [ ] Update the VM provisioning scripts, if needed (e.g., OpenFOAM version) - [ ] Update this release checklist (`tools/release_pull_request_template.md`) - [ ] Advertise and celebrate! :tada: :beers: From 5800f21b163051afd6b0633300780639680ab673 Mon Sep 17 00:00:00 2001 From: Gerasimos Chourdakis Date: Fri, 11 Mar 2022 14:27:29 +0100 Subject: [PATCH 03/31] Document compatibility with OpenFOAM 9 --- docs/openfoam-support.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/openfoam-support.md b/docs/openfoam-support.md index b341f1ab..7195ad5b 100644 --- a/docs/openfoam-support.md +++ b/docs/openfoam-support.md @@ -29,13 +29,14 @@ We provide version-specific [release archives](https://github.com/precice/openfo - [OpenFOAM v1812-v2112](https://github.com/precice/openfoam-adapter) or newer - [OpenFOAM v1612-v1806](https://github.com/precice/openfoam-adapter/tree/OpenFOAMv1806) (not tested) - OpenFOAM Foundation (openfoam.org) - secondary, consider experimental: + - [OpenFOAM 9](https://github.com/precice/openfoam-adapter/tree/OpenFOAM9) (rename also `solver` to `motionSolver` in `constant/dynamicMeshDict`) - [OpenFOAM 8](https://github.com/precice/openfoam-adapter/tree/OpenFOAM8) - [OpenFOAM 7](https://github.com/precice/openfoam-adapter/tree/OpenFOAM7) - - [OpenFOAM 6](https://github.com/precice/openfoam-adapter/tree/OpenFOAM6) + - [OpenFOAM 6](https://github.com/precice/openfoam-adapter/tree/OpenFOAM6) (modify also `residualControl` to `outerResidualControl` in `system/fvSolution`) - [OpenFOAM 5.x](https://github.com/precice/openfoam-adapter/tree/OpenFOAM5) - [OpenFOAM 4.0/4.1](https://github.com/precice/openfoam-adapter/tree/OpenFOAM4) (not tested) -Known not supported versions: OpenFOAM 9 ([issue - contributions welcome](https://github.com/precice/openfoam-adapter/issues/200)), OpenFOAM v1606+ or older, OpenFOAM 3 or older, foam-extend (any version). +Known not supported versions: OpenFOAM v1606+ or older, OpenFOAM 3 or older, foam-extend (any version). ## Supported OpenFOAM solvers From 94eadabacaa232a3465ed021d389aa865e88ff4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Simonis?= Date: Mon, 14 Mar 2022 14:50:10 +0100 Subject: [PATCH 04/31] Add redirect_from adapter-openfoam.html --- docs/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/README.md b/docs/README.md index 36027891..ab1265f1 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,6 +1,7 @@ --- title: The OpenFOAM adapter permalink: adapter-openfoam-overview.html +redirect_from: adapter-openfoam.html keywords: adapter, openfoam, cite, versions summary: An OpenFOAM function object for CHT, FSI, and fluid-fluid coupled simulations using preCICE. --- From bf38c42a197ca9b85b33cf16575010653cea53db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Simonis?= Date: Wed, 13 Apr 2022 08:58:34 +0200 Subject: [PATCH 05/31] Add website update (#226) --- .github/workflows/update-website.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .github/workflows/update-website.yml diff --git a/.github/workflows/update-website.yml b/.github/workflows/update-website.yml new file mode 100644 index 00000000..ecdd6dbe --- /dev/null +++ b/.github/workflows/update-website.yml @@ -0,0 +1,22 @@ +name: Update website +on: + push: + branches: + - 'develop' + paths: + - 'docs/**' +jobs: + trigger: + runs-on: ubuntu-latest + env: + WORKFLOW_FILENAME: update-submodules.yml + steps: + - name: Trigger workflow + run: | + curl \ + --request POST \ + --url https://api.github.com/repos/precice/precice.github.io/actions/workflows/$WORKFLOW_FILENAME/dispatches \ + --header "authorization: token ${{ secrets.WORKFLOW_DISPATCH_TOKEN }}" \ + --header "Accept: application/vnd.github.v3+json" \ + --data '{"ref":"master"}' \ + --fail From a95da52062c2f503ce58d9509c3e47f5efdbf149 Mon Sep 17 00:00:00 2001 From: Gerasimos Chourdakis Date: Sat, 23 Apr 2022 09:32:29 +0200 Subject: [PATCH 06/31] Add hint for foamHasLibrary in Troubleshooting --- docs/get.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/get.md b/docs/get.md index 461dd461..f144efe6 100644 --- a/docs/get.md +++ b/docs/get.md @@ -39,6 +39,15 @@ The following are common problems that may appear during building the OpenFOAM a The `Allwmake` script prints the environment variables it uses in the beginning (as well as in `Allwmake.log`) and it writes the building commands in the file `wmake.log`. Afterwards, it checks (using `ldd`) if the library was linked correctly and writes the output to `ldd.log`. **Please check these files and include them in your report if you have need help.** +If you don't have access to the log files, you can also try running `foamHasLibrary -verbose precice libpreciceAdapterFunctionObject`, which should lead to the following message: + +```text +Can load "precice" +Can load "libpreciceAdapterFunctionObject" +``` + +If the libraries are available but cannot be loaded, the most common issue is conflicting or missing dependencies. Run `ldd ${FOAM_USER_LIBBIN}/libpreciceAdapterFunctionObject.so` and check for any undefined symbols messages at the bottom. + ### Unknown function type `preciceAdapterFunctionObject`
From 3aa1005da92758031f4597754baae4028df254e9 Mon Sep 17 00:00:00 2001 From: Gerasimos Chourdakis Date: Tue, 5 Jul 2022 12:01:01 +0200 Subject: [PATCH 07/31] Bump OpenFOAM to v2206 and preCICE to v2.4.0 (#230) --- .github/workflows/build-custom.yml | 5 +++++ .github/workflows/build.yml | 4 ++-- .github/workflows/install-dependencies.sh | 10 +++++----- CHANGELOG.md | 2 ++ README.md | 2 +- changelog-entries/230.md | 1 + docs/openfoam-support.md | 8 ++++---- tools/release_pull_request_template.md | 2 +- 8 files changed, 21 insertions(+), 13 deletions(-) create mode 100644 changelog-entries/230.md diff --git a/.github/workflows/build-custom.yml b/.github/workflows/build-custom.yml index d1651454..045de61e 100644 --- a/.github/workflows/build-custom.yml +++ b/.github/workflows/build-custom.yml @@ -19,6 +19,7 @@ on: required: true type: choice options: + - OpenFOAMv2206 - OpenFOAMv2112 - OpenFOAMv2106 - OpenFOAMv2012 @@ -76,6 +77,10 @@ jobs: id: installOpenFOAM run: | case "${{ github.event.inputs.versionOpenFOAM }}" in + OpenFOAMv2206) + wget -q -O - https://dl.openfoam.com/add-debian-repo.sh | sudo bash + sudo apt-get install openfoam2206-dev + echo "::set-output name=openfoam_exec::/usr/bin/openfoam2206";; OpenFOAMv2112) wget -q -O - https://dl.openfoam.com/add-debian-repo.sh | sudo bash sudo apt-get install openfoam2112-dev diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2a7d3981..5e388dce 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,4 +1,4 @@ -name: Build with OpenFOAM v2112 +name: Build with OpenFOAM v2206 on: push: branches-ignore: @@ -39,4 +39,4 @@ jobs: snapshot: '/' exclude: '/boot /data /dev /mnt /proc /run /sys' - name: Build OpenFOAM-preCICE adapter - run: /usr/bin/openfoam2112 ./Allwmake + run: /usr/bin/openfoam2206 ./Allwmake diff --git a/.github/workflows/install-dependencies.sh b/.github/workflows/install-dependencies.sh index 3c2f2363..27418e32 100755 --- a/.github/workflows/install-dependencies.sh +++ b/.github/workflows/install-dependencies.sh @@ -1,9 +1,9 @@ #!/bin/bash -e -# Install OpenFOAM v2112 +# Install OpenFOAM v2206 wget -q -O - https://dl.openfoam.com/add-debian-repo.sh | sudo bash -sudo apt-get install openfoam2112-dev +sudo apt-get install openfoam2206-dev -# Install preCICE v2.3.0 -wget https://github.com/precice/precice/releases/download/v2.3.0/libprecice2_2.3.0_focal.deb -sudo apt install ./libprecice2_2.3.0_focal.deb +# Install preCICE v2.4.0 +wget https://github.com/precice/precice/releases/download/v2.4.0/libprecice2_2.4.0_focal.deb +sudo apt install ./libprecice2_2.4.0_focal.deb diff --git a/CHANGELOG.md b/CHANGELOG.md index 16d551a9..63510b7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ Read more details in the issue [#52: Releases and versioning](https://github.com ## [Unreleased] +### Changed + ## [v1.1.0] 2022-02-08 ### Added diff --git a/README.md b/README.md index 6602e0ef..211c7ce3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # OpenFOAM-preCICE adapter -[![Build with OpenFOAM v2112](https://github.com/precice/openfoam-adapter/actions/workflows/build.yml/badge.svg?branch=develop)](https://github.com/precice/openfoam-adapter/actions/workflows/build.yml) +[![Build with OpenFOAM v2206](https://github.com/precice/openfoam-adapter/actions/workflows/build.yml/badge.svg?branch=develop)](https://github.com/precice/openfoam-adapter/actions/workflows/build.yml) [![Changelog](https://img.shields.io/badge/Keep%20a%20Changelog--555.svg?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9IiNmMTVkMzAiIHZpZXdCb3g9IjAgMCAxODcgMTg1Ij48cGF0aCBkPSJNNjIgN2MtMTUgMy0yOCAxMC0zNyAyMmExMjIgMTIyIDAgMDAtMTggOTEgNzQgNzQgMCAwMDE2IDM4YzYgOSAxNCAxNSAyNCAxOGE4OSA4OSAwIDAwMjQgNCA0NSA0NSAwIDAwNiAwbDMtMSAxMy0xYTE1OCAxNTggMCAwMDU1LTE3IDYzIDYzIDAgMDAzNS01MiAzNCAzNCAwIDAwLTEtNWMtMy0xOC05LTMzLTE5LTQ3LTEyLTE3LTI0LTI4LTM4LTM3QTg1IDg1IDAgMDA2MiA3em0zMCA4YzIwIDQgMzggMTQgNTMgMzEgMTcgMTggMjYgMzcgMjkgNTh2MTJjLTMgMTctMTMgMzAtMjggMzhhMTU1IDE1NSAwIDAxLTUzIDE2bC0xMyAyaC0xYTUxIDUxIDAgMDEtMTItMWwtMTctMmMtMTMtNC0yMy0xMi0yOS0yNy01LTEyLTgtMjQtOC0zOWExMzMgMTMzIDAgMDE4LTUwYzUtMTMgMTEtMjYgMjYtMzMgMTQtNyAyOS05IDQ1LTV6TTQwIDQ1YTk0IDk0IDAgMDAtMTcgNTQgNzUgNzUgMCAwMDYgMzJjOCAxOSAyMiAzMSA0MiAzMiAyMSAyIDQxLTIgNjAtMTRhNjAgNjAgMCAwMDIxLTE5IDUzIDUzIDAgMDA5LTI5YzAtMTYtOC0zMy0yMy01MWE0NyA0NyAwIDAwLTUtNWMtMjMtMjAtNDUtMjYtNjctMTgtMTIgNC0yMCA5LTI2IDE4em0xMDggNzZhNTAgNTAgMCAwMS0yMSAyMmMtMTcgOS0zMiAxMy00OCAxMy0xMSAwLTIxLTMtMzAtOS01LTMtOS05LTEzLTE2YTgxIDgxIDAgMDEtNi0zMiA5NCA5NCAwIDAxOC0zNSA5MCA5MCAwIDAxNi0xMmwxLTJjNS05IDEzLTEzIDIzLTE2IDE2LTUgMzItMyA1MCA5IDEzIDggMjMgMjAgMzAgMzYgNyAxNSA3IDI5IDAgNDJ6bS00My03M2MtMTctOC0zMy02LTQ2IDUtMTAgOC0xNiAyMC0xOSAzN2E1NCA1NCAwIDAwNSAzNGM3IDE1IDIwIDIzIDM3IDIyIDIyLTEgMzgtOSA0OC0yNGE0MSA0MSAwIDAwOC0yNCA0MyA0MyAwIDAwLTEtMTJjLTYtMTgtMTYtMzEtMzItMzh6bS0yMyA5MWgtMWMtNyAwLTE0LTItMjEtN2EyNyAyNyAwIDAxLTEwLTEzIDU3IDU3IDAgMDEtNC0yMCA2MyA2MyAwIDAxNi0yNWM1LTEyIDEyLTE5IDI0LTIxIDktMyAxOC0yIDI3IDIgMTQgNiAyMyAxOCAyNyAzM3MtMiAzMS0xNiA0MGMtMTEgOC0yMSAxMS0zMiAxMXptMS0zNHYxNGgtOFY2OGg4djI4bDEwLTEwaDExbC0xNCAxNSAxNyAxOEg5NnoiLz48L3N2Zz4K)](https://github.com/precice/openfoam-adapter/blob/develop/CHANGELOG.md) GNU GPL license diff --git a/changelog-entries/230.md b/changelog-entries/230.md new file mode 100644 index 00000000..a4c3d0f5 --- /dev/null +++ b/changelog-entries/230.md @@ -0,0 +1 @@ +- OpenFOAM version bumped to v2206 in GitHub Actions (including preCICE v2.3.0 --> v2.4.0) and documentation [#230](https://github.com/precice/openfoam-adapter/pull/230). diff --git a/docs/openfoam-support.md b/docs/openfoam-support.md index 7195ad5b..29beb897 100644 --- a/docs/openfoam-support.md +++ b/docs/openfoam-support.md @@ -7,14 +7,14 @@ summary: Recent OpenFOAM.com versions work out-of-the-box. Recent OpenFOAM.org v ## How to get OpenFOAM -The easiest way to start is to get binary packages for your Linux distribution. For example, to [get OpenFOAM v2112 on Ubuntu](https://develop.openfoam.com/Development/openfoam/-/wikis/precompiled/debian#precompiled-packages-debianubuntu): +The easiest way to start is to get binary packages for your Linux distribution. For example, to [get OpenFOAM v2206 on Ubuntu](https://develop.openfoam.com/Development/openfoam/-/wikis/precompiled/debian#precompiled-packages-debianubuntu): ```bash # Add the signing key, add the repository, update: wget -q -O - https://dl.openfoam.com/add-debian-repo.sh | sudo bash -# Install OpenFOAM v2112: -sudo apt-get install openfoam2112-dev +# Install OpenFOAM v2206: +sudo apt-get install openfoam2206-dev ``` As these steps change your `.profile`, you need to log out and in again to make OpenFOAM fully discoverable. @@ -26,7 +26,7 @@ OpenFOAM is a project with long history and many forks, of which we try to suppo We provide version-specific [release archives](https://github.com/precice/openfoam-adapter/releases/latest) and respective Git branches for: - OpenCFD / ESI (openfoam.com) - main focus: - - [OpenFOAM v1812-v2112](https://github.com/precice/openfoam-adapter) or newer + - [OpenFOAM v1812-v2206](https://github.com/precice/openfoam-adapter) or newer - [OpenFOAM v1612-v1806](https://github.com/precice/openfoam-adapter/tree/OpenFOAMv1806) (not tested) - OpenFOAM Foundation (openfoam.org) - secondary, consider experimental: - [OpenFOAM 9](https://github.com/precice/openfoam-adapter/tree/OpenFOAM9) (rename also `solver` to `motionSolver` in `constant/dynamicMeshDict`) diff --git a/tools/release_pull_request_template.md b/tools/release_pull_request_template.md index cd604177..ca72ea81 100644 --- a/tools/release_pull_request_template.md +++ b/tools/release_pull_request_template.md @@ -66,7 +66,7 @@ master <-- OpenFOAM4 <-- OpenFOAM5 <-- OpenFOAM6 <-- OpenFOAM7 <-- OpenFOAM8 <-- - [ ] Create a Release on GitHub - [ ] Download an archive of the repository (i.e., no `.git/` or `.gitignore`) for each version and attach to the release. Use the link `https://github.com/precice/openfoam-adapter/archive/refs/heads/BRANCH.tar.gz` (substitute `BRANCH`). Rename the folder in each archive to reflect the name of the archive. - - branch `master`: archive `openfoam-adapter_v1.0.0_OpenFOAMv1812-v2112.tar.gz` (adjust `v2112` to the latest supported, and `v1.0.0` to the actual version) + - branch `master`: archive `openfoam-adapter_v1.0.0_OpenFOAMv1812-v2206-newer.tar.gz` (adjust `v2206` to the latest supported, and `v1.0.0` to the actual version) - branch `OpenFOAM4`: archive `openfoam-adapter_v1.0.0_OpenFOAM4_5_v1806.tar.gz` - branch `OpenFOAM6`: archive `openfoam-adapter_v1.0.0_OpenFOAM6_experimental.tar.gz` - branch `OpenFOAM7`: archive `openfoam-adapter_v1.0.0_OpenFOAM7_experimental.tar.gz` From ddb52756467d967b2a6e1b4b03124000b677f228 Mon Sep 17 00:00:00 2001 From: Gerasimos Chourdakis Date: Mon, 1 Aug 2022 08:35:05 +0200 Subject: [PATCH 08/31] Document compatibility with OpenFOAM 10 --- docs/openfoam-support.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/openfoam-support.md b/docs/openfoam-support.md index 29beb897..309ad587 100644 --- a/docs/openfoam-support.md +++ b/docs/openfoam-support.md @@ -29,6 +29,7 @@ We provide version-specific [release archives](https://github.com/precice/openfo - [OpenFOAM v1812-v2206](https://github.com/precice/openfoam-adapter) or newer - [OpenFOAM v1612-v1806](https://github.com/precice/openfoam-adapter/tree/OpenFOAMv1806) (not tested) - OpenFOAM Foundation (openfoam.org) - secondary, consider experimental: + - [OpenFOAM 10](https://github.com/precice/openfoam-adapter/tree/OpenFOAM10) (several [changes to the tutorials](https://github.com/precice/tutorials/tree/OpenFOAM10) are also needed, read the [discussion](https://github.com/precice/tutorials/pull/283)) - [OpenFOAM 9](https://github.com/precice/openfoam-adapter/tree/OpenFOAM9) (rename also `solver` to `motionSolver` in `constant/dynamicMeshDict`) - [OpenFOAM 8](https://github.com/precice/openfoam-adapter/tree/OpenFOAM8) - [OpenFOAM 7](https://github.com/precice/openfoam-adapter/tree/OpenFOAM7) From 9a3799e5e75f905e16e0b88ce88ad460f8db399c Mon Sep 17 00:00:00 2001 From: Gerasimos Chourdakis Date: Mon, 1 Aug 2022 08:38:03 +0200 Subject: [PATCH 09/31] Fix Markdown linter error in compatibility docs --- docs/openfoam-support.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/openfoam-support.md b/docs/openfoam-support.md index 309ad587..f16ed3d0 100644 --- a/docs/openfoam-support.md +++ b/docs/openfoam-support.md @@ -29,7 +29,7 @@ We provide version-specific [release archives](https://github.com/precice/openfo - [OpenFOAM v1812-v2206](https://github.com/precice/openfoam-adapter) or newer - [OpenFOAM v1612-v1806](https://github.com/precice/openfoam-adapter/tree/OpenFOAMv1806) (not tested) - OpenFOAM Foundation (openfoam.org) - secondary, consider experimental: - - [OpenFOAM 10](https://github.com/precice/openfoam-adapter/tree/OpenFOAM10) (several [changes to the tutorials](https://github.com/precice/tutorials/tree/OpenFOAM10) are also needed, read the [discussion](https://github.com/precice/tutorials/pull/283)) + - [OpenFOAM 10](https://github.com/precice/openfoam-adapter/tree/OpenFOAM10) (several [changes to the tutorials](https://github.com/precice/tutorials/tree/OpenFOAM10) are also needed, read the [discussion](https://github.com/precice/tutorials/pull/283)) - [OpenFOAM 9](https://github.com/precice/openfoam-adapter/tree/OpenFOAM9) (rename also `solver` to `motionSolver` in `constant/dynamicMeshDict`) - [OpenFOAM 8](https://github.com/precice/openfoam-adapter/tree/OpenFOAM8) - [OpenFOAM 7](https://github.com/precice/openfoam-adapter/tree/OpenFOAM7) From 68d782bd506273c4c5ce2f48cad13fcfcf899a41 Mon Sep 17 00:00:00 2001 From: Gerasimos Chourdakis Date: Mon, 1 Aug 2022 09:54:19 +0200 Subject: [PATCH 10/31] Add OpenFOAM 10 to GitHub Actions workflow (#234) --- .github/workflows/build-custom.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/build-custom.yml b/.github/workflows/build-custom.yml index 045de61e..0d0dc4e5 100644 --- a/.github/workflows/build-custom.yml +++ b/.github/workflows/build-custom.yml @@ -25,6 +25,7 @@ on: - OpenFOAMv2012 - OpenFOAMv2006 - OpenFOAMv1912 + - OpenFOAM10 - OpenFOAM9 - OpenFOAM8 - OpenFOAM7 @@ -101,6 +102,12 @@ jobs: wget -q -O - https://dl.openfoam.com/add-debian-repo.sh | sudo bash sudo apt-get install openfoam1912-dev echo "::set-output name=openfoam_exec::/usr/bin/openfoam1912";; + OpenFOAM10) + sudo sh -c "wget -O - https://dl.openfoam.org/gpg.key | apt-key add -" + sudo add-apt-repository http://dl.openfoam.org/ubuntu + sudo apt-get update + sudo apt-get -y install openfoam10 + echo "::set-output name=openfoam_exec::. /opt/openfoam10/etc/bashrc &&";; OpenFOAM9) sudo sh -c "wget -O - https://dl.openfoam.org/gpg.key | apt-key add -" sudo add-apt-repository http://dl.openfoam.org/ubuntu From 14c5ca18cf9afd108ff521b89634459e2b9fde62 Mon Sep 17 00:00:00 2001 From: Gerasimos Chourdakis Date: Tue, 2 Aug 2022 08:42:40 +0200 Subject: [PATCH 11/31] Fix a few language typos --- Adapter.C | 2 +- Allwmake | 2 +- CHT/CHT.H | 2 +- FSI/ForceBase.C | 2 +- Interface.C | 2 +- docs/extend.md | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Adapter.C b/Adapter.C index e4da2dca..78e41c10 100644 --- a/Adapter.C +++ b/Adapter.C @@ -511,7 +511,7 @@ void preciceAdapter::Adapter::writeCouplingData() void preciceAdapter::Adapter::initialize() { - DEBUG(adapterInfo("Initalizing the preCICE solver interface...")); + DEBUG(adapterInfo("Initializing the preCICE solver interface...")); timestepPrecice_ = precice_->initialize(); preciceInitialized_ = true; diff --git a/Allwmake b/Allwmake index 3313220b..6909f976 100755 --- a/Allwmake +++ b/Allwmake @@ -20,7 +20,7 @@ ADAPTER_TARGET_DIR="${FOAM_USER_LIBBIN:-}" DOC_COMPATIBILITY="https://www.precice.org/adapter-openfoam-support.html" ################################################################################ -# Funtion to print to screen and copy to a logfile +# Function to print to screen and copy to a logfile log() { echo "$@" | tee -a "Allwmake.log" } diff --git a/CHT/CHT.H b/CHT/CHT.H index 2f0c527f..bbda2fca 100644 --- a/CHT/CHT.H +++ b/CHT/CHT.H @@ -49,7 +49,7 @@ protected: //- Determine the solver type std::string determineSolverType(); - //- Read the CHT-related options from the adapter's configuraiton file + //- Read the CHT-related options from the adapter's configuration file bool readConfig(const IOdictionary& adapterConfig); public: diff --git a/FSI/ForceBase.C b/FSI/ForceBase.C index 37e1c9e8..84b5e3d9 100644 --- a/FSI/ForceBase.C +++ b/FSI/ForceBase.C @@ -154,7 +154,7 @@ void preciceAdapter::FSI::ForceBase::writeToBuffer(double* buffer, const auto& surface = tsurface(); // Pressure forces - // FIXME: We need to substract the reference pressure for incompressible calculations + // FIXME: We need to subtract the reference pressure for incompressible calculations if (solverType_.compare("incompressible") == 0) { forceField.boundaryFieldRef()[patchID] = diff --git a/Interface.C b/Interface.C index c90ab5bc..24840bc1 100644 --- a/Interface.C +++ b/Interface.C @@ -237,7 +237,7 @@ void preciceAdapter::Interface::configureMesh(const fvMesh& mesh) const List faceField = mesh.boundaryMesh()[patchIDs_.at(j)].localFaces(); const Field pointCoords = mesh.boundaryMesh()[patchIDs_.at(j)].localPoints(); - // Array to store coordiantes in preCICE format + // Array to store coordinates in preCICE format double triCoords[faceField.size() * triaPerQuad * nodesPerTria * componentsPerNode]; unsigned int coordIndex = 0; diff --git a/docs/extend.md b/docs/extend.md index 1b5c591a..337e10f7 100644 --- a/docs/extend.md +++ b/docs/extend.md @@ -11,7 +11,7 @@ The OpenFOAM adapter separates the core functionality (e.g. calling preCICE meth ![simplified UML diagram](images/docs-adapter-openfoam-modules.svg) -While in the begining the adapter only included a module for conjugate heat transfer, [a module for fluid-structure interaction](https://github.com/precice/openfoam-adapter/pull/56) and [a module for fluid-fluid coupling](https://github.com/precice/openfoam-adapter/pull/67) have been added since then. +While in the beginning the adapter only included a module for conjugate heat transfer, [a module for fluid-structure interaction](https://github.com/precice/openfoam-adapter/pull/56) and [a module for fluid-fluid coupling](https://github.com/precice/openfoam-adapter/pull/67) have been added since then. ## Starting points From c8f612e1a597c6b50d84a7528a2c44edab9fb2ee Mon Sep 17 00:00:00 2001 From: solids4foam <110133789+solids4foam@users.noreply.github.com> Date: Mon, 8 Aug 2022 18:49:59 +0100 Subject: [PATCH 12/31] Adds functionality to allow FSI to work with solids4foam as the solid solver (#236) Co-authored-by: Philip Cardiff Co-authored-by: Gerasimos Chourdakis --- .gitignore | 1 + Adapter.C | 14 +++++++--- FSI/Displacement.C | 59 ++++++++++++++++++++++++++++++++++------ FSI/DisplacementDelta.C | 8 +++--- FSI/FSI.C | 18 ++++++++---- FSI/FSI.H | 3 ++ FSI/Force.C | 46 +++++++++++++++++++++++++++++-- FSI/Force.H | 6 +++- FSI/ForceBase.C | 25 +++++++++-------- changelog-entries/236.md | 1 + docs/README.md | 4 +-- docs/config.md | 4 +-- docs/openfoam-support.md | 2 +- 13 files changed, 148 insertions(+), 43 deletions(-) create mode 100644 changelog-entries/236.md diff --git a/.gitignore b/.gitignore index d273fd25..b7f69be9 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,7 @@ # OpenFOAM / WMake lnInclude/ Make/linux64GccDPInt32Opt/ +Make/darwin64ClangDPInt32Opt/ # Editors .cproject diff --git a/Adapter.C b/Adapter.C index 78e41c10..5c0df07b 100644 --- a/Adapter.C +++ b/Adapter.C @@ -757,6 +757,12 @@ void preciceAdapter::Adapter::storeMeshPoints() void preciceAdapter::Adapter::reloadMeshPoints() { + if (!mesh_.moving()) + { + DEBUG(adapterInfo("Mesh points not moved as the mesh is not moving")); + return; + } + // In Foam::polyMesh::movePoints. // TODO: The function movePoints overwrites the pointer to the old mesh. // Therefore, if you revert the mesh, the oldpointer will be set to the points, which are the new values. @@ -1301,8 +1307,8 @@ void preciceAdapter::Adapter::readMeshCheckpoint() { DEBUG(adapterInfo("Reading a mesh checkpoint...")); - //TODO only the meshPhi field is here, which is a surfaceScalarField. The other fields can be removed. - // Reload all the fields of type mesh surfaceScalarField + // TODO only the meshPhi field is here, which is a surfaceScalarField. The other fields can be removed. + // Reload all the fields of type mesh surfaceScalarField for (uint i = 0; i < meshSurfaceScalarFields_.size(); i++) { // Load the volume field @@ -1529,8 +1535,8 @@ void preciceAdapter::Adapter::teardown() } meshVolVectorFieldCopies_.clear(); - //TODO for the internal volume - // volScalarInternal + // TODO for the internal volume + // volScalarInternal for (uint i = 0; i < volScalarInternalFieldCopies_.size(); i++) { delete volScalarInternalFieldCopies_.at(i); diff --git a/FSI/Displacement.C b/FSI/Displacement.C index 90a6e2de..398a65ed 100644 --- a/FSI/Displacement.C +++ b/FSI/Displacement.C @@ -7,8 +7,10 @@ preciceAdapter::FSI::Displacement::Displacement( const std::string namePointDisplacement, const std::string nameCellDisplacement) : pointDisplacement_( - const_cast( - &mesh.lookupObject(namePointDisplacement))), + namePointDisplacement == "unused" + ? nullptr + : const_cast( + &mesh.lookupObject(namePointDisplacement))), cellDisplacement_( const_cast( &mesh.lookupObject(nameCellDisplacement))), @@ -37,13 +39,52 @@ void preciceAdapter::FSI::Displacement::initialize() void preciceAdapter::FSI::Displacement::write(double* buffer, bool meshConnectivity, const unsigned int dim) { /* TODO: Implement - * We need two nested for-loops for each patch, - * the outer for the locations and the inner for the dimensions. - * See the preCICE writeBlockVectorData() implementation. - */ - FatalErrorInFunction - << "Writing displacements is not supported." - << exit(FatalError); + * We need two nested for-loops for each patch, + * the outer for the locations and the inner for the dimensions. + * See the preCICE writeBlockVectorData() implementation. + */ + + // Copy the displacement field from OpenFOAM to the buffer + + if (this->locationType_ == LocationType::faceCenters) + { + // For every boundary patch of the interface + for (const label patchID : patchIDs_) + { + // Write the displacement to the preCICE buffer + // For every cell of the patch + forAll(cellDisplacement_->boundaryField()[patchID], i) + { + for (unsigned int d = 0; d < dim; ++d) + buffer[i * dim + d] = + cellDisplacement_->boundaryField()[patchID][i][d]; + } + } + } + else if (this->locationType_ == LocationType::faceNodes) + { + DEBUG(adapterInfo( + "Please be aware of issues with using 'locationType faceNodes' " + "in parallel. \n" + "See https://github.com/precice/openfoam-adapter/issues/153.", + "warning")); + + // For every boundary patch of the interface + for (const label patchID : patchIDs_) + { + // Write the displacement to the preCICE buffer + // For every cell of the patch + forAll(pointDisplacement_->boundaryField()[patchID], i) + { + const labelList& meshPoints = + mesh_.boundaryMesh()[patchID].meshPoints(); + + for (unsigned int d = 0; d < dim; ++d) + buffer[i * dim + d] = + pointDisplacement_->internalField()[meshPoints[i]][d]; + } + } + } } diff --git a/FSI/DisplacementDelta.C b/FSI/DisplacementDelta.C index ca4e4c2a..53b56240 100644 --- a/FSI/DisplacementDelta.C +++ b/FSI/DisplacementDelta.C @@ -37,10 +37,10 @@ void preciceAdapter::FSI::DisplacementDelta::initialize() void preciceAdapter::FSI::DisplacementDelta::write(double* buffer, bool meshConnectivity, const unsigned int dim) { /* TODO: Implement - * We need two nested for-loops for each patch, - * the outer for the locations and the inner for the dimensions. - * See the preCICE writeBlockVectorData() implementation. - */ + * We need two nested for-loops for each patch, + * the outer for the locations and the inner for the dimensions. + * See the preCICE writeBlockVectorData() implementation. + */ FatalErrorInFunction << "Writing displacementDeltas is not supported." << exit(FatalError); diff --git a/FSI/FSI.C b/FSI/FSI.C index a10e0326..5050bb31 100644 --- a/FSI/FSI.C +++ b/FSI/FSI.C @@ -27,7 +27,9 @@ bool preciceAdapter::FSI::FluidStructureInteraction::configure(const IOdictionar // addWriters() and addReaders(). // Check the solver type and determine it if needed if ( - solverType_.compare("compressible") == 0 || solverType_.compare("incompressible") == 0) + solverType_.compare("compressible") == 0 + || solverType_.compare("incompressible") == 0 + || solverType_.compare("solid") == 0) { DEBUG(adapterInfo("Known solver type: " + solverType_)); } @@ -38,7 +40,7 @@ bool preciceAdapter::FSI::FluidStructureInteraction::configure(const IOdictionar } else { - DEBUG(adapterInfo("Determining the solver type for the FSI module... (override by setting solverType to one of {compressible, incompressible})")); + DEBUG(adapterInfo("Determining the solver type for the FSI module... (override by setting solverType to one of {compressible, incompressible, solid})")); solverType_ = determineSolverType(); } @@ -54,8 +56,8 @@ bool preciceAdapter::FSI::FluidStructureInteraction::readConfig(const IOdictiona DEBUG(adapterInfo(" user-defined solver type : " + solverType_)); /* TODO: Read the names of any needed fields and parameters. - * Include the force here? - */ + * Include the force here? + */ // Read the name of the pointDisplacement field (if different) namePointDisplacement_ = FSIdict.lookupOrDefault("namePointDisplacement", "pointDisplacement"); @@ -65,6 +67,10 @@ bool preciceAdapter::FSI::FluidStructureInteraction::readConfig(const IOdictiona nameCellDisplacement_ = FSIdict.lookupOrDefault("nameCellDisplacement", "cellDisplacement"); DEBUG(adapterInfo(" cellDisplacement field name : " + nameCellDisplacement_)); + // Read the name of the solidForce field (if different) + nameSolidForce_ = FSIdict.lookupOrDefault("nameSolidForce", "solidForce"); + DEBUG(adapterInfo(" solidForce field name : " + nameSolidForce_)); + return true; } @@ -117,7 +123,7 @@ bool preciceAdapter::FSI::FluidStructureInteraction::addWriters(std::string data { interface->addCouplingDataWriter( dataName, - new Force(mesh_, solverType_) /* TODO: Add any other arguments here */ + new Force(mesh_, solverType_, nameSolidForce_) /* TODO: Add any other arguments here */ ); DEBUG(adapterInfo("Added writer: Force.")); } @@ -165,7 +171,7 @@ bool preciceAdapter::FSI::FluidStructureInteraction::addReaders(std::string data { interface->addCouplingDataReader( dataName, - new Force(mesh_, solverType_) /* TODO: Add any other arguments here */ + new Force(mesh_, solverType_, nameSolidForce_) /* TODO: Add any other arguments here */ ); DEBUG(adapterInfo("Added reader: Force.")); } diff --git a/FSI/FSI.H b/FSI/FSI.H index 3e93d77e..008da0a6 100644 --- a/FSI/FSI.H +++ b/FSI/FSI.H @@ -34,6 +34,9 @@ protected: //- Name of the pointDisplacement field std::string nameCellDisplacement_ = "cellDisplacement"; + //- Name of the force field used by the solid + std::string nameSolidForce_ = "solidForce"; + /* TODO: Declare here any parameters that should be read from / the configuration file. See CHT/CHT.H for reference. / We want to support in-house solvers with different field names, diff --git a/FSI/Force.C b/FSI/Force.C index 46c298fb..d2867f30 100644 --- a/FSI/Force.C +++ b/FSI/Force.C @@ -4,7 +4,8 @@ using namespace Foam; preciceAdapter::FSI::Force::Force( const Foam::fvMesh& mesh, - const std::string solverType) + const std::string solverType, + const std::string nameSolidForce) : ForceBase(mesh, solverType) { Force_ = new volVectorField( @@ -19,6 +20,17 @@ preciceAdapter::FSI::Force::Force( "fdim", dimensionSet(1, 1, -2, 0, 0, 0, 0), Foam::vector::zero)); + + if (mesh_.foundObject(nameSolidForce)) + { + solidForce_ = + &const_cast( + mesh_.lookupObject(nameSolidForce)); + } + else + { + solidForce_ = nullptr; + } } void preciceAdapter::FSI::Force::write(double* buffer, bool meshConnectivity, const unsigned int dim) @@ -28,7 +40,37 @@ void preciceAdapter::FSI::Force::write(double* buffer, bool meshConnectivity, co void preciceAdapter::FSI::Force::read(double* buffer, const unsigned int dim) { - this->readFromBuffer(buffer); + // Copy the force field from the buffer to OpenFOAM + + // Here we assume that a force volVectorField exists, which is used by + // the OpenFOAM solver + + // Set boundary forces + for (unsigned int j = 0; j < patchIDs_.size(); j++) + { + // Get the ID of the current patch + const unsigned int patchID = patchIDs_.at(j); + + if (this->locationType_ == LocationType::faceCenters) + { + // Make a force field + vectorField& force = solidForce_->boundaryFieldRef()[patchID]; + + // Copy the forces from the buffer into the force field + forAll(force, i) + { + for (unsigned int d = 0; d < dim; ++d) + force[i][d] = buffer[i * dim + d]; + } + } + else if (this->locationType_ == LocationType::faceNodes) + { + // Here we could easily interpolate the face values to point values + // and assign them to some field, but I guess there is no need + // unless it will be used + notImplemented("Read forces not implemented for faceNodes!"); + } + } } bool preciceAdapter::FSI::Force::isLocationTypeSupported(const bool meshConnectivity) const diff --git a/FSI/Force.H b/FSI/Force.H index 062e42c0..851863f3 100644 --- a/FSI/Force.H +++ b/FSI/Force.H @@ -15,11 +15,15 @@ private: //- Force field Foam::volVectorField* Force_; + //- Solid force field + Foam::volVectorField* solidForce_; + public: //- Constructor Force( const Foam::fvMesh& mesh, - const std::string solverType); + const std::string solverType, + const std::string nameSolidForce); //- Write the forces values into the buffer void write(double* buffer, bool meshConnectivity, const unsigned int dim) override; diff --git a/FSI/ForceBase.C b/FSI/ForceBase.C index 84b5e3d9..57f36875 100644 --- a/FSI/ForceBase.C +++ b/FSI/ForceBase.C @@ -9,22 +9,24 @@ preciceAdapter::FSI::ForceBase::ForceBase( : mesh_(mesh), solverType_(solverType) { - //What about type "basic"? - if (solverType_.compare("incompressible") != 0 && solverType_.compare("compressible") != 0) + // What about type "basic"? + if (solverType_.compare("incompressible") != 0 + && solverType_.compare("compressible") != 0 + && solverType_.compare("solid") != 0) { FatalErrorInFunction << "Force based calculations only support " - << "compressible or incompressible solver types." + << "compressible, incompressible, or solid solver types." << exit(FatalError); } dataType_ = vector; } -//Calculate viscous force +// Calculate viscous force Foam::tmp preciceAdapter::FSI::ForceBase::devRhoReff() const { - //For turbulent flows + // For turbulent flows typedef compressible::turbulenceModel cmpTurbModel; typedef incompressible::turbulenceModel icoTurbModel; @@ -52,7 +54,7 @@ Foam::tmp preciceAdapter::FSI::ForceBase::devRhoReff() } } -//lookup correct rho +// lookup correct rho Foam::tmp preciceAdapter::FSI::ForceBase::rho() const { // If volScalarField exists, read it from registry (for compressible cases) @@ -88,10 +90,9 @@ Foam::tmp preciceAdapter::FSI::ForceBase::rho() const } } -//lookup correct mu +// lookup correct mu Foam::tmp preciceAdapter::FSI::ForceBase::mu() const { - if (solverType_.compare("incompressible") == 0) { typedef immiscibleIncompressibleTwoPhaseMixture iitpMixture; @@ -191,10 +192,10 @@ void preciceAdapter::FSI::ForceBase::writeToBuffer(double* buffer, void preciceAdapter::FSI::ForceBase::readFromBuffer(double* buffer) const { /* TODO: Implement - * We need two nested for-loops for each patch, - * the outer for the locations and the inner for the dimensions. - * See the preCICE readBlockVectorData() implementation. - */ + * We need two nested for-loops for each patch, + * the outer for the locations and the inner for the dimensions. + * See the preCICE readBlockVectorData() implementation. + */ FatalErrorInFunction << "Reading forces is not supported." << exit(FatalError); diff --git a/changelog-entries/236.md b/changelog-entries/236.md new file mode 100644 index 00000000..e80f533f --- /dev/null +++ b/changelog-entries/236.md @@ -0,0 +1 @@ +- Added functionality to allow use of solids4foam with the OpenFOAM adapter diff --git a/docs/README.md b/docs/README.md index ab1265f1..a1a437c5 100644 --- a/docs/README.md +++ b/docs/README.md @@ -18,9 +18,9 @@ This adapter can read/write the following fields: - Heat flux (read + write) - Sink temperature (read + write) - Heat transfer coefficient (read + write) -- Force (write) +- Force (read + write) - Stress (write) -- Displacement (read) +- Displacement (read + write) - Displacement delta (read) - Pressure (read + write) - Pressure gradient (read + write) diff --git a/docs/config.md b/docs/config.md index 6371bac7..b40a8ab1 100644 --- a/docs/config.md +++ b/docs/config.md @@ -120,7 +120,7 @@ writeData ); ``` -For fluid-structure interaction, `writeData` can be `Force` or `Stress`, where `Stress` is essentially a force vector scaled by the cell face in spatial coordinates (with any postfix), thus, a conservative quantity as well.`readData` can be `Displacement` and `DisplacementDelta` (with any postfix). `DisplacementDelta` refers to the last coupling time step, which needs to considered in the case of subcycling. +For fluid-structure interaction, `writeData` can be `Force` or `Stress`, where `Stress` is essentially a force vector scaled by the cell face in spatial coordinates (with any postfix), thus, a conservative quantity as well. `readData` can be `Displacement` and `DisplacementDelta` (with any postfix). `DisplacementDelta` refers to the last coupling time step, which needs to considered in the case of subcycling. Structure solvers (such as solids4Foam) can also write `Displacement` and read `Force`. {% warning %} You will run into problems when you use `Displacement(Delta)` as write data set and execute RBF mappings in parallel. This would affect users who use OpenFOAM and the adapter as the Solid participant in order to compute solid mechanics with OpenFOAM (currently not officially supported at all). Have a look [at this issue on GitHub](https://github.com/precice/openfoam-adapter/issues/153) for details. @@ -312,7 +312,7 @@ and depends on the density (`rho [ 1 -3 0 0 0 0 0 ]`) and heat capacity (`Cp #### Fluid-structure interaction -The adapter's FSI functionality supports both compressible and incompressible solvers. +The adapter's FSI functionality supports both compressible and incompressible solvers, as well as solid (e.g., solids4Foam) solvers. For incompressible solvers, it tries to read uniform values for the density and kinematic viscosity (if it is not already available) from the `FSI` subdictionary of `preciceDict`: diff --git a/docs/openfoam-support.md b/docs/openfoam-support.md index f16ed3d0..76c217f7 100644 --- a/docs/openfoam-support.md +++ b/docs/openfoam-support.md @@ -41,7 +41,7 @@ Known not supported versions: OpenFOAM v1606+ or older, OpenFOAM 3 or older, foa ## Supported OpenFOAM solvers -We support mainstream OpenFOAM solvers such as pimpleFoam (for FSI) or buoyantPimpleFoam, buoyantSimpleFoam, laplacianFoam (for CHT). Our community has tried the adapter with multiple different solvers that support function objects. +We support mainstream OpenFOAM solvers such as pimpleFoam and solids4Foam for FSI, buoyantPimpleFoam, buoyantSimpleFoam, and laplacianFoam for CHT, or pimpleFoam and sonicLiquidFoam for FF. Our community has, additionally, tried the adapter with multiple different solvers that support function objects. ## Notes on OpenFOAM features From 6eb97b39556a62bbfe15aabc76b153e8a525b5fe Mon Sep 17 00:00:00 2001 From: solids4foam <110133789+solids4foam@users.noreply.github.com> Date: Sat, 13 Aug 2022 11:15:06 +0100 Subject: [PATCH 13/31] Displacement reading: Allow mesh motion solvers without a pointDisplacement field (#241) Co-authored-by: Gerasimos Chourdakis --- FSI/Displacement.C | 18 ++++++++------ changelog-entries/241.md | 1 + docs/config.md | 52 +++++++++++++++++++++++++++++----------- 3 files changed, 50 insertions(+), 21 deletions(-) create mode 100644 changelog-entries/241.md diff --git a/FSI/Displacement.C b/FSI/Displacement.C index 398a65ed..a83c0a42 100644 --- a/FSI/Displacement.C +++ b/FSI/Displacement.C @@ -107,14 +107,18 @@ void preciceAdapter::FSI::Displacement::read(double* buffer, const unsigned int for (unsigned int d = 0; d < dim; ++d) cellDisplacement_->boundaryFieldRef()[patchID][i][d] = buffer[i * dim + d]; } - // Get a reference to the displacement on the point patch in order to overwrite it - vectorField& pointDisplacementFluidPatch( - refCast( - pointDisplacement_->boundaryFieldRef()[patchID])); - // Overwrite the node based patch using the interpolation objects and the cell based vector field - // Afterwards, continue as usual - pointDisplacementFluidPatch = interpolationObjects_[j]->faceToPointInterpolate(cellDisplacement_->boundaryField()[patchID]); + if (pointDisplacement_ != nullptr) + { + // Get a reference to the displacement on the point patch in order to overwrite it + vectorField& pointDisplacementFluidPatch( + refCast( + pointDisplacement_->boundaryFieldRef()[patchID])); + + // Overwrite the node based patch using the interpolation objects and the cell based vector field + // Afterwards, continue as usual + pointDisplacementFluidPatch = interpolationObjects_[j]->faceToPointInterpolate(cellDisplacement_->boundaryField()[patchID]); + } } else if (this->locationType_ == LocationType::faceNodes) { diff --git a/changelog-entries/241.md b/changelog-entries/241.md new file mode 100644 index 00000000..2072005a --- /dev/null +++ b/changelog-entries/241.md @@ -0,0 +1 @@ +- Enabled mesh motion solvers that do not register a pointDisplacement field (such as the RBFMeshMotionSolver from solids4foam) to work with the adapter [#241](https://github.com/precice/openfoam-adapter/pull/241) diff --git a/docs/config.md b/docs/config.md index b40a8ab1..4c05ec09 100644 --- a/docs/config.md +++ b/docs/config.md @@ -181,7 +181,7 @@ interface * For `readData(Displacement)` or `DisplacementDelta`, you need the following: * `type movingWallVelocity` for the interface (e.g. `flap`) in `0/U`, * `type fixedValue` for the interface (e.g. `flap`) in the `0/pointDisplacement`, and - * `solver displacementLaplacian` in the `constant/dynamicMeshDict`. + * `solver displacementLaplacian` in the `constant/dynamicMeshDict`. The solver [`RBFMeshMotionSolver` from solids4foam is also known to work](https://github.com/precice/openfoam-adapter/pull/241), currently (August 2022) with the develop branch of the OpenFOAM adapter and the nextRelease branch of solids4foam. ```c++ // File 0/U @@ -332,7 +332,7 @@ Some optional parameters can allow the adapter to work with more solvers, whose The adapter tries to automatically determine the solver type, based on the dictionaries that the solver uses. However, you may manually specify the solver type to be `basic`, -`incompressible` or `compressible` for a CHT or FSI simulation: +`incompressible` or `compressible` for a CHT simulation: ```c++ CHT @@ -341,6 +341,15 @@ CHT }; ``` +or the `incompressible`, `compressible`, or `solid` (e.g., for solids4Foam) for an FSI simulation: + +```c++ +FSI +{ + solverType solid; +} +``` + This will force the adapter use the boundary condition implementations for the respective type. @@ -354,21 +363,36 @@ file (the values correspond to the default values): ```c++ CHT { - # Temperature field - nameT T1; - # Thermal conductivity - nameKappa k1; - # Density - nameRho rho1; - # Heat capacity for constant pressure - nameCp Cp1; - # Prandtl number - namePr Pr1; - # Turbulent thermal diffusivity - nameAlphat alphat1; + // Temperature field + nameT T1; + // Thermal conductivity + nameKappa k1; + // Density + nameRho rho1; + // Heat capacity for constant pressure + nameCp Cp1; + // Prandtl number + namePr Pr1; + // Turbulent thermal diffusivity + nameAlphat alphat1; }; ``` +Similarly for FSI simulations: + +```c++ +FSI +{ + // Displacement fields + namePointDisplacement pointD; + nameCellDisplacement D; + // Force field on the solid + forceFieldName solidForce; +} +``` + +Use the option `namePointDisplacement unused;` for solvers that do not create a pointDisplacement field, such as the RBFMeshMotionSolver. + #### Debugging The adapter also recognizes a few more parameters, which are mainly used in debugging or development. From 6f7d44004d9245e02481978ba048492274ec2594 Mon Sep 17 00:00:00 2001 From: Gerasimos Chourdakis Date: Fri, 9 Sep 2022 09:55:55 +0200 Subject: [PATCH 14/31] Document collaboration with other function objects --- docs/config.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/config.md b/docs/config.md index 4c05ec09..ec6294c6 100644 --- a/docs/config.md +++ b/docs/config.md @@ -224,6 +224,8 @@ This directs the solver to use the `preciceAdapterFunctionObject` function objec which is part of the `libpreciceAdapterFunctionObject.so` shared library. The name `preCICE_Adapter` can be arbitrary. +If you are using other function objects in your simulation, add the preCICE adapter to the end of the list. The adapter will then be executed last, which is important, as the adapter also controls the end of the simulation. When the end of the simulation is detected, the adapter also triggers the `end()` method method of all function objects. + *** ## Advanced configuration From c8ee7804afa11cae8cb9002bfe4dfb2d5a86e964 Mon Sep 17 00:00:00 2001 From: Gerasimos Chourdakis Date: Mon, 19 Sep 2022 14:58:54 +0200 Subject: [PATCH 15/31] Change xy-plane check error to warning (#246) co-authored-by: arved.enders-seidlitz@posteo.de --- Interface.C | 10 +++++----- changelog-entries/246.md | 1 + docs/config.md | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) create mode 100644 changelog-entries/246.md diff --git a/Interface.C b/Interface.C index 24840bc1..6761c96c 100644 --- a/Interface.C +++ b/Interface.C @@ -153,11 +153,11 @@ void preciceAdapter::Interface::configureMesh(const fvMesh& mesh) } else { - FatalErrorInFunction - << "It seems like you are using preCICE in 2D and your geometry is not located int the xy-plane. " - "The OpenFOAM adapter implementation supports preCICE 2D cases only with the z-axis as out-of-plane direction." - "Please rotate your geometry so that the geometry is located in the xy-plane." - << exit(FatalError); + adapterInfo("It seems like you are using preCICE in 2D and your geometry is not located int the xy-plane. " + "The OpenFOAM adapter implementation supports preCICE 2D cases only with the z-axis as out-of-plane direction." + "Please rotate your geometry so that the geometry is located in the xy-plane." + "If you are running a 2D axisymmetric case just ignore this.", + "warning"); } } } diff --git a/changelog-entries/246.md b/changelog-entries/246.md new file mode 100644 index 00000000..fc4af6bd --- /dev/null +++ b/changelog-entries/246.md @@ -0,0 +1 @@ +- Changed the xy-plane error to a warning, to support 2D axisymmetric cases. [#246](https://github.com/precice/openfoam-adapter/pull/246) diff --git a/docs/config.md b/docs/config.md index ec6294c6..af108678 100644 --- a/docs/config.md +++ b/docs/config.md @@ -404,7 +404,7 @@ The user can toggle debug messages at [build time](https://precice.org/adapter-o ## Coupling OpenFOAM with 2D solvers -The adapter asks preCICE for the dimensions of the coupling data defined in the `precice-config.xml` (2D or 3D). It then automatically operates in either 3D (normal) or 2D (reduced) mode, with z-axis being the out-of-plane dimension. [Read more](https://github.com/precice/openfoam-adapter/pull/96). +The adapter asks preCICE for the dimensions of the coupling data defined in the `precice-config.xml` (2D or 3D). It then automatically operates in either 3D (normal) or 2D (reduced) mode, with z-axis being the out-of-plane dimension. [Read more](https://github.com/precice/openfoam-adapter/pull/96). In 2D mode, the adapter also supports axisymmetric cases. ## Porting your older cases to the current configuration format From 451bc05c0cfe19c3963a61434dd8645ee5485e72 Mon Sep 17 00:00:00 2001 From: Gerasimos Chourdakis Date: Mon, 19 Sep 2022 14:59:17 +0200 Subject: [PATCH 16/31] Cleanup virtual/override/final (#245) --- CHT/HeatFlux.H | 26 +++++++++++++------------- CHT/HeatTransferCoefficient.H | 26 +++++++++++++------------- CHT/SinkTemperature.H | 4 ++-- CHT/Temperature.H | 4 ++-- FF/Pressure.H | 4 ++-- FF/PressureGradient.H | 4 ++-- FF/Velocity.H | 4 ++-- FF/VelocityGradient.H | 8 ++++---- FSI/Displacement.H | 10 +++++----- FSI/DisplacementDelta.H | 10 +++++----- FSI/Force.H | 10 +++++----- FSI/Stress.H | 10 +++++----- changelog-entries/245.md | 1 + preciceAdapterFunctionObject.H | 16 ++++++++-------- 14 files changed, 69 insertions(+), 68 deletions(-) create mode 100644 changelog-entries/245.md diff --git a/CHT/HeatFlux.H b/CHT/HeatFlux.H index d1e34c0e..ea21eac7 100644 --- a/CHT/HeatFlux.H +++ b/CHT/HeatFlux.H @@ -33,16 +33,16 @@ public: //- Compute heat flux values from the temperature field // and write them into the buffer - virtual void write(double* buffer, bool meshConnectivity, const unsigned int dim); + void write(double* buffer, bool meshConnectivity, const unsigned int dim) final; //- Read heat flux values from the buffer and assign them to // the gradient of the temperature field - virtual void read(double* buffer, const unsigned int dim); + void read(double* buffer, const unsigned int dim) final; - bool isLocationTypeSupported(const bool meshConnectivity) const override; + bool isLocationTypeSupported(const bool meshConnectivity) const final; //- Get the name of the current data field - std::string getDataName() const override; + std::string getDataName() const final; //- Destructor virtual ~HeatFlux() {}; @@ -59,10 +59,10 @@ protected: KappaEff_Compressible* Kappa_; //- Wrapper for the extract() method of the corresponding KappaEff class - virtual void extractKappaEff(uint patchID, bool meshConnectivity); + void extractKappaEff(uint patchID, bool meshConnectivity) final; //- Wrapper for the getAt() method of the corresponding KappaEff class - virtual Foam::scalar getKappaEffAt(int i); + Foam::scalar getKappaEffAt(int i) final; public: //- Constructor @@ -71,7 +71,7 @@ public: const std::string nameT); //- Destructor - virtual ~HeatFlux_Compressible(); + ~HeatFlux_Compressible() final; }; //- Implementation of the HeatFlux for incompresible, turbulent flow solvers @@ -85,10 +85,10 @@ protected: KappaEff_Incompressible* Kappa_; //- Wrapper for the extract() method of the corresponding KappaEff class - virtual void extractKappaEff(uint patchID, bool meshConnectivity); + void extractKappaEff(uint patchID, bool meshConnectivity) final; //- Wrapper for the getAt() method of the corresponding KappaEff class - virtual Foam::scalar getKappaEffAt(int i); + Foam::scalar getKappaEffAt(int i) final; public: //- Constructor @@ -101,7 +101,7 @@ public: const std::string nameAlphat); //- Destructor - virtual ~HeatFlux_Incompressible(); + ~HeatFlux_Incompressible() final; }; //- Implementation of the HeatFlux for basic solvers @@ -115,10 +115,10 @@ protected: KappaEff_Basic* Kappa_; //- Wrapper for the extract() method of the corresponding KappaEff class - virtual void extractKappaEff(uint patchID, bool meshConnectivity); + void extractKappaEff(uint patchID, bool meshConnectivity) final; //- Wrapper for the getAt() method of the corresponding KappaEff class - virtual Foam::scalar getKappaEffAt(int i); + Foam::scalar getKappaEffAt(int i) final; public: //- Constructor @@ -128,7 +128,7 @@ public: const std::string nameKappa); //- Destructor - virtual ~HeatFlux_Basic(); + ~HeatFlux_Basic() final; }; } diff --git a/CHT/HeatTransferCoefficient.H b/CHT/HeatTransferCoefficient.H index f0caa2de..c09edd00 100644 --- a/CHT/HeatTransferCoefficient.H +++ b/CHT/HeatTransferCoefficient.H @@ -35,15 +35,15 @@ public: const std::string nameT); //- Write the heat transfer coefficient values into the buffer - virtual void write(double* buffer, bool meshConnectivity, const unsigned int dim); + void write(double* buffer, bool meshConnectivity, const unsigned int dim) final; //- Read the heat transfer coefficient values from the buffer - virtual void read(double* buffer, const unsigned int dim); + void read(double* buffer, const unsigned int dim) final; - bool isLocationTypeSupported(const bool meshConnectivity) const override; + bool isLocationTypeSupported(const bool meshConnectivity) const final; //- Get the name of the current data field - std::string getDataName() const override; + std::string getDataName() const final; //- Destructor virtual ~HeatTransferCoefficient() {}; @@ -60,10 +60,10 @@ protected: KappaEff_Compressible* Kappa_; //- Wrapper for the extract() method of the corresponding KappaEff class - virtual void extractKappaEff(uint patchID, bool meshConnectivity); + void extractKappaEff(uint patchID, bool meshConnectivity) final; //- Wrapper for the getAt() method of the corresponding KappaEff class - virtual Foam::scalar getKappaEffAt(int i); + Foam::scalar getKappaEffAt(int i) final; public: //- Constructor @@ -72,7 +72,7 @@ public: const std::string nameT); //- Destructor - virtual ~HeatTransferCoefficient_Compressible(); + ~HeatTransferCoefficient_Compressible() final; }; //- Implementation of the HeatTransferCoefficient for incompresible, turbulent flow solvers @@ -86,10 +86,10 @@ protected: KappaEff_Incompressible* Kappa_; //- Wrapper for the extract() method of the corresponding KappaEff class - virtual void extractKappaEff(uint patchID, bool meshConnectivity); + void extractKappaEff(uint patchID, bool meshConnectivity) final; //- Wrapper for the getAt() method of the corresponding KappaEff class - virtual Foam::scalar getKappaEffAt(int i); + Foam::scalar getKappaEffAt(int i) final; public: //- Constructor @@ -102,7 +102,7 @@ public: const std::string nameAlphat); //- Destructor - virtual ~HeatTransferCoefficient_Incompressible(); + ~HeatTransferCoefficient_Incompressible() final; }; @@ -117,10 +117,10 @@ protected: KappaEff_Basic* Kappa_; //- Wrapper for the extract() method of the corresponding KappaEff class - virtual void extractKappaEff(uint patchID, bool meshConnectivity); + void extractKappaEff(uint patchID, bool meshConnectivity) final; //- Wrapper for the getAt() method of the corresponding KappaEff class - virtual Foam::scalar getKappaEffAt(int i); + Foam::scalar getKappaEffAt(int i) final; public: //- Constructor @@ -130,7 +130,7 @@ public: const std::string nameKappa); //- Destructor - virtual ~HeatTransferCoefficient_Basic(); + ~HeatTransferCoefficient_Basic() final; }; } diff --git a/CHT/SinkTemperature.H b/CHT/SinkTemperature.H index 8b66896e..68493e54 100644 --- a/CHT/SinkTemperature.H +++ b/CHT/SinkTemperature.H @@ -31,10 +31,10 @@ public: //- Read the sink temperature values from the buffer void read(double* buffer, const unsigned int dim); - bool isLocationTypeSupported(const bool meshConnectivity) const override; + bool isLocationTypeSupported(const bool meshConnectivity) const final; //- Get the name of the current data field - std::string getDataName() const override; + std::string getDataName() const final; }; } diff --git a/CHT/Temperature.H b/CHT/Temperature.H index 0ce85a7c..d3e17d5b 100644 --- a/CHT/Temperature.H +++ b/CHT/Temperature.H @@ -31,10 +31,10 @@ public: //- Read the temperature values from the buffer void read(double* buffer, const unsigned int dim); - bool isLocationTypeSupported(const bool meshConnectivity) const override; + bool isLocationTypeSupported(const bool meshConnectivity) const final; //- Get the name of the current data field - std::string getDataName() const override; + std::string getDataName() const final; }; } diff --git a/FF/Pressure.H b/FF/Pressure.H index 5506de53..32993489 100644 --- a/FF/Pressure.H +++ b/FF/Pressure.H @@ -30,10 +30,10 @@ public: //- Read the pressure values from the buffer void read(double* buffer, const unsigned int dim); - bool isLocationTypeSupported(const bool meshConnectivity) const override; + bool isLocationTypeSupported(const bool meshConnectivity) const final; //- Get the name of the current data field - std::string getDataName() const override; + std::string getDataName() const final; }; } diff --git a/FF/PressureGradient.H b/FF/PressureGradient.H index 47920b7f..95094f3c 100644 --- a/FF/PressureGradient.H +++ b/FF/PressureGradient.H @@ -30,10 +30,10 @@ public: //- Read the pressure gradient values from the buffer void read(double* buffer, const unsigned int dim); - bool isLocationTypeSupported(const bool meshConnectivity) const override; + bool isLocationTypeSupported(const bool meshConnectivity) const final; //- Get the name of the current data field - std::string getDataName() const override; + std::string getDataName() const final; }; } diff --git a/FF/Velocity.H b/FF/Velocity.H index 17c0dc19..8c5e396b 100644 --- a/FF/Velocity.H +++ b/FF/Velocity.H @@ -30,10 +30,10 @@ public: //- Read the velocity values from the buffer void read(double* buffer, const unsigned int dim); - bool isLocationTypeSupported(const bool meshConnectivity) const override; + bool isLocationTypeSupported(const bool meshConnectivity) const final; //- Get the name of the current data field - std::string getDataName() const override; + std::string getDataName() const final; }; } diff --git a/FF/VelocityGradient.H b/FF/VelocityGradient.H index c3ce7368..3e1f16da 100644 --- a/FF/VelocityGradient.H +++ b/FF/VelocityGradient.H @@ -25,15 +25,15 @@ public: const std::string nameU); //- Write the velocity gradient values into the buffer - void write(double* buffer, bool meshConnectivity, const unsigned int dim) override; + void write(double* buffer, bool meshConnectivity, const unsigned int dim) final; //- Read the velocity gradient values from the buffer - void read(double* buffer, const unsigned int dim) override; + void read(double* buffer, const unsigned int dim) final; - bool isLocationTypeSupported(const bool meshConnectivity) const override; + bool isLocationTypeSupported(const bool meshConnectivity) const final; //- Get the name of the current data field - std::string getDataName() const override; + std::string getDataName() const final; }; } diff --git a/FSI/Displacement.H b/FSI/Displacement.H index 64631852..8b7d5216 100644 --- a/FSI/Displacement.H +++ b/FSI/Displacement.H @@ -36,19 +36,19 @@ public: const std::string nameCellDisplacement); //- Write the displacement values into the buffer - void write(double* buffer, bool meshConnectivity, const unsigned int dim) override; + void write(double* buffer, bool meshConnectivity, const unsigned int dim) final; //- Read the displacement values from the buffer - void read(double* buffer, const unsigned int dim) override; + void read(double* buffer, const unsigned int dim) final; - bool isLocationTypeSupported(const bool meshConnectivity) const override; + bool isLocationTypeSupported(const bool meshConnectivity) const final; //- Get the name of the current data field - std::string getDataName() const override; + std::string getDataName() const final; //- We need to initialize the cell-based vector and the interpolation object // in case we want to use the faceCenter location for the coupling - void initialize() override; + void initialize() final; }; } diff --git a/FSI/DisplacementDelta.H b/FSI/DisplacementDelta.H index 25f162c5..27c57e51 100644 --- a/FSI/DisplacementDelta.H +++ b/FSI/DisplacementDelta.H @@ -36,19 +36,19 @@ public: const std::string nameCellDisplacement); //- Write the displacementDelta values into the buffer - void write(double* buffer, bool meshConnectivity, const unsigned int dim) override; + void write(double* buffer, bool meshConnectivity, const unsigned int dim) final; //- Read the displacementDelta values from the buffer - void read(double* buffer, const unsigned int dim) override; + void read(double* buffer, const unsigned int dim) final; - bool isLocationTypeSupported(const bool meshConnectivity) const override; + bool isLocationTypeSupported(const bool meshConnectivity) const final; //- Get the name of the current data field - virtual std::string getDataName() const; + std::string getDataName() const; //- We need to initialize the cell-based vector and the interpolation object // in case we want to use the faceCenter location for the coupling - void initialize() override; + void initialize() final; }; } diff --git a/FSI/Force.H b/FSI/Force.H index 851863f3..268b2ee3 100644 --- a/FSI/Force.H +++ b/FSI/Force.H @@ -26,18 +26,18 @@ public: const std::string nameSolidForce); //- Write the forces values into the buffer - void write(double* buffer, bool meshConnectivity, const unsigned int dim) override; + void write(double* buffer, bool meshConnectivity, const unsigned int dim) final; //- Read the forces values from the buffer - void read(double* buffer, const unsigned int dim) override; + void read(double* buffer, const unsigned int dim) final; - bool isLocationTypeSupported(const bool meshConnectivity) const override; + bool isLocationTypeSupported(const bool meshConnectivity) const final; //- Get the name of the current data field - std::string getDataName() const override; + std::string getDataName() const final; //- Returns the normal vectors multiplied by the face area - Foam::tmp getFaceVectors(const unsigned int patchID) const override; + Foam::tmp getFaceVectors(const unsigned int patchID) const final; //- Destructor ~Force(); diff --git a/FSI/Stress.H b/FSI/Stress.H index 0e82aa34..24f62034 100644 --- a/FSI/Stress.H +++ b/FSI/Stress.H @@ -27,18 +27,18 @@ public: const std::string solverType); //- Write the stress values into the buffer - void write(double* buffer, bool meshConnectivity, const unsigned int dim) override; + void write(double* buffer, bool meshConnectivity, const unsigned int dim) final; //- Read the stress values from the buffer - void read(double* buffer, const unsigned int dim) override; + void read(double* buffer, const unsigned int dim) final; - bool isLocationTypeSupported(const bool meshConnectivity) const override; + bool isLocationTypeSupported(const bool meshConnectivity) const final; //- Get the name of the current data field - std::string getDataName() const override; + std::string getDataName() const final; //- Returns the face normal vectors (no multiplication by area) - Foam::tmp getFaceVectors(const unsigned int patchID) const override; + Foam::tmp getFaceVectors(const unsigned int patchID) const final; //- Destructor ~Stress(); diff --git a/changelog-entries/245.md b/changelog-entries/245.md new file mode 100644 index 00000000..6e6fa6b6 --- /dev/null +++ b/changelog-entries/245.md @@ -0,0 +1 @@ +- Changed virtual function declarations to explicitly define one (only) of virtual/override/final. If you need to extend a method marked as `final`, please report. [#245](https://github.com/precice/openfoam-adapter/pull/245) diff --git a/preciceAdapterFunctionObject.H b/preciceAdapterFunctionObject.H index 99f9f5fd..63af7132 100644 --- a/preciceAdapterFunctionObject.H +++ b/preciceAdapterFunctionObject.H @@ -106,25 +106,25 @@ public: //- Destructor - virtual ~preciceAdapterFunctionObject(); + ~preciceAdapterFunctionObject() final; // Member Functions //- Read the preciceAdapterFunctionObject data - virtual bool read(const dictionary&); + bool read(const dictionary&) final; //- Execute in the beginning of each time-loop, after the first one - virtual bool execute(); + bool execute() final; //- Execute at the final time-loop, after execute() - virtual bool end(); + bool end() final; //- Write the preciceAdapterFunctionObject - virtual bool write(); + bool write() final; //- Called at the end of Time::adjustDeltaT() if adjustTime is true - virtual bool adjustTimeStep(); + bool adjustTimeStep() final; /* // NOTE: If you add a new module that needs to execute methods @@ -132,10 +132,10 @@ public: // you may put your calls inside the following methods. // Update for changes of mesh - virtual void updateMesh(const mapPolyMesh& mpm); + void updateMesh(const mapPolyMesh& mpm) final; // Update for changes of mesh - virtual void movePoints(const polyMesh& mesh); + void movePoints(const polyMesh& mesh) final; */ }; From 2c7909abcef8d016bcb6c2c716668ffa29c7b51a Mon Sep 17 00:00:00 2001 From: Gerasimos Chourdakis Date: Mon, 19 Sep 2022 20:50:36 +0200 Subject: [PATCH 17/31] Extend Allwmake suggestions for possible problems (#220) Co-authored-by: David Schneider --- Allwmake | 43 ++++++++++++++++++++++++++++------------ changelog-entries/220.md | 1 + 2 files changed, 31 insertions(+), 13 deletions(-) create mode 100644 changelog-entries/220.md diff --git a/Allwmake b/Allwmake index 6909f976..a9be8fd5 100755 --- a/Allwmake +++ b/Allwmake @@ -24,6 +24,11 @@ DOC_COMPATIBILITY="https://www.precice.org/adapter-openfoam-support.html" log() { echo "$@" | tee -a "Allwmake.log" } +# Function to print warnings +warning() { + log "WARNING: $*" + export ADAPTER_WARNINGS="true" +} ################################################################################ # Information header @@ -33,23 +38,27 @@ log "Building the OpenFOAM-preCICE adapter..." export ADAPTER_PREP_FLAGS export ADAPTER_TARGET_DIR -if pkg-config libprecice; then - ADAPTER_PKG_CONFIG_CFLAGS="$(pkg-config --silence-errors --cflags libprecice)" - ADAPTER_PKG_CONFIG_LIBS="$(pkg-config --silence-errors --libs libprecice)" +# Check if pkg-config is available and get the config for preCICE +ADAPTER_PKG_CONFIG_CFLAGS="" +ADAPTER_PKG_CONFIG_LIBS="" +if command -v pkg-config >/dev/null 2>&1; then + if pkg-config libprecice; then + ADAPTER_PKG_CONFIG_CFLAGS="$(pkg-config --silence-errors --cflags libprecice)" + ADAPTER_PKG_CONFIG_LIBS="$(pkg-config --silence-errors --libs libprecice)" + log "" + log "If not already known by the system, preCICE may be located using:" + log " pkg-config --cflags libprecice = ${ADAPTER_PKG_CONFIG_CFLAGS}" + log " pkg-config --libs libprecice = ${ADAPTER_PKG_CONFIG_LIBS}" + else + warning "pkg-config configuration file 'libprecice.pc' was not found in the PKG_CONFIG_PATH. + Check the preCICE documentation page 'Linking to preCICE' for more details, or proceed if you know what you are doing." + fi else - log "WARNING: No configuration file 'libprecice.pc' was found in the PKG_CONFIG_PATH." - log "Check the preCICE documentation page 'Linking to preCICE' for more details, or proceed if you know what you are doing." - ADAPTER_PKG_CONFIG_CFLAGS="" - ADAPTER_PKG_CONFIG_LIBS="" + warning "pkg-config is not installed and cannot be used to detect the preCICE installation. If building succeeds, ignore this warning." fi export ADAPTER_PKG_CONFIG_CFLAGS export ADAPTER_PKG_CONFIG_LIBS -log "" -log "If not already known by the system, preCICE may be located using:" -log " pkg-config --cflags libprecice = ${ADAPTER_PKG_CONFIG_CFLAGS}" -log " pkg-config --libs libprecice = ${ADAPTER_PKG_CONFIG_LIBS}" - # Check if an OpenFOAM environment is available log "" log "Current OpenFOAM environment:" @@ -89,6 +98,7 @@ if ! adapter_build_command 2>&1 | tee wmake.log || log "- Make sure you are using a compatible version of the adapter for your OpenFOAM version:" log " ${DOC_COMPATIBILITY}" log "- Is preCICE discoverable at compile time? Check the content of ADAPTER_PKG_CONFIG_CFLAGS above." + log "Attach your Allwmake.log and wmake.log when asking for help." exit 1 else ADAPTER_WMAKE_UNDEFINED_SYMBOLS=$(grep -c -E "undefined|not defined" wmake.log) || echo "Everything looks fine in wmake.log." @@ -97,9 +107,16 @@ else if [ "${ADAPTER_WMAKE_UNDEFINED_SYMBOLS}" -gt 0 ] || [ "${ADAPTER_LD_UNDEFINED_SYMBOLS}" -gt 0 ]; then log "=== ERROR: Building completed with linking problems: there were undefined symbols. ===" log "Possible causes:" - log "- Is preCICE discoverable at runtime? Check the content of ADAPTER_PKG_CONFIG_LIBS above." + log "- Is preCICE discoverable at runtime? Check the content of pkg-config output above." + log "- Did anything go wrong while installing preCICE? Can you run any other preCICE tutorials?" + log "- Did anything go wrong while installing OpenFOAM? Can you run any other OpenFOAM tutorials?" log "See wmake.log and ldd.log for more details." + log "Attach your Allwmake.log, wmake.log, and ldd.log when asking for help." else log "=== OK: Building completed successfully! ===" fi fi + +if [ "${ADAPTER_WARNINGS:-}" = "true" ]; then + echo "There have been warnings. Check the log above." +fi diff --git a/changelog-entries/220.md b/changelog-entries/220.md new file mode 100644 index 00000000..ff26bc30 --- /dev/null +++ b/changelog-entries/220.md @@ -0,0 +1 @@ +- Added a warning for trying to build without pkg-config being available and more suggestions for possible problems [#220](https://github.com/precice/openfoam-adapter/pull/220). From 43fef267d6eb2b6b2ed6f4128470c88be75435b4 Mon Sep 17 00:00:00 2001 From: Gerasimos Chourdakis Date: Mon, 19 Sep 2022 21:11:36 +0200 Subject: [PATCH 18/31] Remove deprecated isReadDataAvailable (#247) --- Interface.C | 54 +++++++++++++++++++--------------------- changelog-entries/247.md | 1 + 2 files changed, 26 insertions(+), 29 deletions(-) create mode 100644 changelog-entries/247.md diff --git a/Interface.C b/Interface.C index 6761c96c..502c6339 100644 --- a/Interface.C +++ b/Interface.C @@ -371,38 +371,34 @@ void preciceAdapter::Interface::createBuffer() void preciceAdapter::Interface::readCouplingData() { - // Are new data available or is the participant subcycling? - if (precice_.isReadDataAvailable()) + // Make every coupling data reader read + for (uint i = 0; i < couplingDataReaders_.size(); i++) { - // Make every coupling data reader read - for (uint i = 0; i < couplingDataReaders_.size(); i++) - { - // Pointer to the current reader - preciceAdapter::CouplingDataUser* - couplingDataReader = couplingDataReaders_.at(i); - - // Make preCICE read vector or scalar data - // and fill the adapter's buffer - if (couplingDataReader->hasVectorData()) - { - precice_.readBlockVectorData( - couplingDataReader->dataID(), - numDataLocations_, - vertexIDs_, - dataBuffer_); - } - else - { - precice_.readBlockScalarData( - couplingDataReader->dataID(), - numDataLocations_, - vertexIDs_, - dataBuffer_); - } + // Pointer to the current reader + preciceAdapter::CouplingDataUser* + couplingDataReader = couplingDataReaders_.at(i); - // Read the received data from the buffer - couplingDataReader->read(dataBuffer_, dim_); + // Make preCICE read vector or scalar data + // and fill the adapter's buffer + if (couplingDataReader->hasVectorData()) + { + precice_.readBlockVectorData( + couplingDataReader->dataID(), + numDataLocations_, + vertexIDs_, + dataBuffer_); + } + else + { + precice_.readBlockScalarData( + couplingDataReader->dataID(), + numDataLocations_, + vertexIDs_, + dataBuffer_); } + + // Read the received data from the buffer + couplingDataReader->read(dataBuffer_, dim_); } } diff --git a/changelog-entries/247.md b/changelog-entries/247.md new file mode 100644 index 00000000..9d0625e1 --- /dev/null +++ b/changelog-entries/247.md @@ -0,0 +1 @@ +- Removed the (deprecated since preCICE v2.5.0) call to isReadDataAvailable. [#247](https://github.com/precice/openfoam-adapter/pull/247) From f521d3c9308b2b75d1e4232ec59a3a38ceb0a7c1 Mon Sep 17 00:00:00 2001 From: Gerasimos Chourdakis Date: Tue, 20 Sep 2022 08:20:41 +0200 Subject: [PATCH 19/31] Remove -j 4 flag, document WM_NCOMPPROCS (#244) * Inform user about WM_NCOMPPROCS, remove -j flag * Document WM_NCOMPPROCS * Add changelog entry * Add default value for unset WM_NCOMPPROCS Co-authored-by: David Schneider --- Allwmake | 6 ++++-- changelog-entries/244.md | 1 + docs/get.md | 3 ++- 3 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 changelog-entries/244.md diff --git a/Allwmake b/Allwmake index a9be8fd5..40b71ea6 100755 --- a/Allwmake +++ b/Allwmake @@ -7,10 +7,11 @@ set -e -u ADAPTER_PREP_FLAGS="" # Build command and options -# In order to compile with multiple threads, add e.g. "-j 4". +# In order to compile with multiple threads, set the environment variable WM_NCOMPPROCS, +# e.g., add "export WM_NCOMP_PROCS=4" to your ~/.bashrc # Make sure that these options are supported by your OpenFOAM version. adapter_build_command(){ - wmake -j 4 libso + wmake libso } # Where should the adapter be built? Default: "${FOAM_USER_LIBBIN}" @@ -64,6 +65,7 @@ log "" log "Current OpenFOAM environment:" log " WM_PROJECT = ${WM_PROJECT:-}" log " WM_PROJECT_VERSION = ${WM_PROJECT_VERSION:-}" +log " WM_NCOMPPROCS = ${WM_NCOMPPROCS:=1} (number of threads for parallel builds)" if [ -z "${WM_PROJECT:-}" ]; then log "" diff --git a/changelog-entries/244.md b/changelog-entries/244.md new file mode 100644 index 00000000..5c24afa9 --- /dev/null +++ b/changelog-entries/244.md @@ -0,0 +1 @@ +- Removed the default `-j 4` option from the wmake command. Instead, documented the `WM_NCOMPPROCS` option of OpenFOAM. [#244](https://github.com/precice/openfoam-adapter/pull/244) diff --git a/docs/get.md b/docs/get.md index f144efe6..535ab09a 100644 --- a/docs/get.md +++ b/docs/get.md @@ -13,12 +13,13 @@ To build the adapter, you need to install a few dependencies and then execute th 4. Execute the build script: `./Allwmake`. * See and adjust the configuration in the beginning of the script first, if needed. * Check for any error messages and suggestions at the end. - * Modify the `adapter_build_command` to e.g. build using more threads, e.g. `wmake -j 4 libso`. The adapter also requires [pkg-config](https://linux.die.net/man/1/pkg-config) to [link to preCICE](https://precice.org/installation-linking.html). This is a very common dependency on Linux and is usually already installed. Adding `-DADAPTER_DEBUG_MODE` flag to the `ADAPTER_PREP_FLAGS` activates additional debug messages. You may also change the target directory or specify the number of threads to use for the compilation. See the comments in `Allwmake` for more. +If you are building the adapter often, you may want to build it in parallel. You can set the environment variable `WM_NCOMPPROCS` to the number of parallel threads you want WMake to use. + Next: [configure and load the adapter](https://precice.org/adapter-openfoam-config.html) or [run a tutorial](https://precice.org/tutorials.html). ## What does the adapter version mean? From 6453f7a57ad51d7b36677acd225a122b5a939e26 Mon Sep 17 00:00:00 2001 From: Gerasimos Chourdakis Date: Thu, 22 Sep 2022 13:15:23 +0200 Subject: [PATCH 20/31] Replace SVG image with PNG in docs (#251) To circumvent wrong font issues --- docs/extend.md | 2 +- .../docs-adapter-openfoam-modules-src.svg | 627 ++++++++++++++++++ docs/images/docs-adapter-openfoam-modules.png | Bin 0 -> 43726 bytes docs/images/docs-adapter-openfoam-modules.svg | 3 - 4 files changed, 628 insertions(+), 4 deletions(-) create mode 100644 docs/images/docs-adapter-openfoam-modules-src.svg create mode 100644 docs/images/docs-adapter-openfoam-modules.png delete mode 100644 docs/images/docs-adapter-openfoam-modules.svg diff --git a/docs/extend.md b/docs/extend.md index 337e10f7..6d7e66b7 100644 --- a/docs/extend.md +++ b/docs/extend.md @@ -9,7 +9,7 @@ summary: "An overview of the OpenFOAM adapter's architecture and which parts to The OpenFOAM adapter separates the core functionality (e.g. calling preCICE methods) from the problem-specific methods (e.g. accessing fields and converting quantities). The latter is encapsulated into "modules", which add only a few lines of code in the core. The following, simplified UML diagram gives an overview: -![simplified UML diagram](images/docs-adapter-openfoam-modules.svg) +![simplified UML diagram](images/docs-adapter-openfoam-modules.png) While in the beginning the adapter only included a module for conjugate heat transfer, [a module for fluid-structure interaction](https://github.com/precice/openfoam-adapter/pull/56) and [a module for fluid-fluid coupling](https://github.com/precice/openfoam-adapter/pull/67) have been added since then. diff --git a/docs/images/docs-adapter-openfoam-modules-src.svg b/docs/images/docs-adapter-openfoam-modules-src.svg new file mode 100644 index 00000000..bde7effc --- /dev/null +++ b/docs/images/docs-adapter-openfoam-modules-src.svg @@ -0,0 +1,627 @@ + + + + + + + + + + + + + + + + + + + + + + + + Adapter + + + + Adapter + + + + + + + + + + + + + + + + + + Interface + + + + Interface + + + + + + + + + + + + + + + + + + CouplingDataUser + + + + CouplingDataUser + + + + + + + + + CHT module + + + + CHT module + + + + + + + + + FSI module + + + + FSI module + + + + + + + + + + + + preciceAdapterFunctionObject + + + + preciceAdapterFunctionObject + + + + + + FF module + + + + Fluid-Fluid +module + + + + + + + + + + + + + * + + + + + * + + + + + + + Viewer does not support full SVG 1.1 + + + diff --git a/docs/images/docs-adapter-openfoam-modules.png b/docs/images/docs-adapter-openfoam-modules.png new file mode 100644 index 0000000000000000000000000000000000000000..9b4a19ce888587baff5094d125859fdbc7d9cba8 GIT binary patch literal 43726 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 WDL+8Aaw6_&8h>wgl6m~cYySq=DHHMl literal 0 HcmV?d00001 diff --git a/docs/images/docs-adapter-openfoam-modules.svg b/docs/images/docs-adapter-openfoam-modules.svg deleted file mode 100644 index 9a679e87..00000000 --- a/docs/images/docs-adapter-openfoam-modules.svg +++ /dev/null @@ -1,3 +0,0 @@ - - -
Adapter
Adapter
Interface
Interface
CouplingDataUser
CouplingDataUser
CHT module
CHT module
FSI module
FSI module
preciceAdapterFunctionObject
preciceAdapterFunctionObject
Fluid-Fluid
module
Fluid-Fluid...
*
*
Viewer does not support full SVG 1.1
\ No newline at end of file From 6473949b05b7f749a2645bbe4b76963fbe512ba8 Mon Sep 17 00:00:00 2001 From: Gerasimos Chourdakis Date: Fri, 23 Sep 2022 11:28:25 +0200 Subject: [PATCH 21/31] Reword warning for nearest-projection mapping (#248) --- Adapter.C | 7 +++---- docs/config.md | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Adapter.C b/Adapter.C index 5c0df07b..238ff4ab 100644 --- a/Adapter.C +++ b/Adapter.C @@ -161,10 +161,9 @@ bool preciceAdapter::Adapter::configFileRead() if (interfacesConfig_.at(i).meshConnectivity == true) { adapterInfo( - "Mesh connectivity is not supported for FSI, as, usually, " - "the Solid participant needs to provide the connectivity information. " - "Therefore, set provideMeshConnectivity = false. " - "Have a look in the adapter documentation for more information. ", + "You have requested mesh connectivity (most probably for nearest-projection mapping) " + "and you have enabled the FSI module. " + "Mapping with connectivity information is not implemented for FSI, only for CHT-related fields. " "warning"); return false; } diff --git a/docs/config.md b/docs/config.md index af108678..cc7c2f28 100644 --- a/docs/config.md +++ b/docs/config.md @@ -279,7 +279,7 @@ Data is obtained at the face centers, then interpolated to face nodes. Here, we It is important to notice that the target data location is again the face center mesh of the coupling partner. In the standard CHT case, where both data sets are exchanged by a nearest-projection mapping, this leads to two interface meshes (centers and nodes) per participant. Having both the centers and nodes defined, we can skip one interpolation step and read data directly to the centers (cf. picture solver B). {% note %} -As already mentioned, the `Fluid` participant does not need to provide the mesh connectivity in case of a standard FSI. Therefore, the `Solid` participant needs to provide it and nothing special needs to be considered compared to other mapping methods. This implementation supports all CHT-related fields, which are mapped with a `consistent` constraint. +This is implemented for all CHT-related fields mapped with a `consistent` constraint, but it is not implemented for the `FSI` and `FF` modules. {% endnote %} ### Additional properties for some solvers From da63afb96560be7cf2b2a18dbd53f983abc806c2 Mon Sep 17 00:00:00 2001 From: Gerasimos Chourdakis Date: Mon, 26 Sep 2022 11:33:52 +0200 Subject: [PATCH 22/31] Document FF module configuration (#254) Co-authored-by: David Schneider --- changelog-entries/254.md | 1 + docs/config.md | 92 ++++++++++++++++++++++++++++------------ 2 files changed, 67 insertions(+), 26 deletions(-) create mode 100644 changelog-entries/254.md diff --git a/changelog-entries/254.md b/changelog-entries/254.md new file mode 100644 index 00000000..99d64769 --- /dev/null +++ b/changelog-entries/254.md @@ -0,0 +1 @@ +- Added more documentation, specifically for configuring the FF module. [#254](https://github.com/precice/openfoam-adapter/pull/254) diff --git a/docs/config.md b/docs/config.md index cc7c2f28..aa37c08a 100644 --- a/docs/config.md +++ b/docs/config.md @@ -11,11 +11,9 @@ In order to run a coupled simulation, you need to: 2. prepare an adapter's configuration file, 3. set the coupling boundaries in the OpenFOAM case, 4. load the adapter, and -5. start all the solvers normally, from the same directory, e.g. in two different terminals. +5. start all the solvers normally, from the same directory, e.g., in two different terminals. -If you prefer, you may find an already prepared case in our [Tutorial for CHT: Flow over a heated plate](https://precice.org/tutorials-flow-over-heated-plate.html). - -You may skip the section _"Advanced configuration"_ in the beginning, as it only concerns special cases. You may also find more details in the [Pull Request #105](https://github.com/precice/openfoam-adapter/pull/105), especially for changes regarding the previous, yaml-based configuration format. +You may skip the section _"Advanced configuration"_ in the beginning, as it only concerns special cases. ## The adapter's configuration file @@ -61,20 +59,22 @@ interfaces The `participant` needs to be the same as the one specified in the `preciceConfig`, which is the main preCICE configuration file. The `preciceConfig` can be a path and needs to be wrapped with quotation marks. -The list `modules` can contain `CHT` or/and `FSI` (separated by space). +The list `modules` can contain `CHT`, `FSI`, or/and `FF` (separated by space). +Each module provides some data fields common in the respective type of simulation, and data fields from different modules can be combined by selecting multiple modules. +For example, this is a valid combination: `modules (CHT FF);`. In the `interfaces`, we specify the coupling interfaces (here only one). The `mesh` needs to be the same as the one specified in the `preciceConfig`. The `patches` specifies a list of the names of the OpenFOAM boundary patches that are participating in the coupled simulation. These need to be defined in the files -included in the `0/` directory. The names of the interfaces (e.g. `Interface1`) are arbitrary and are not used. +included in the `0/` directory. The names of the interfaces (e.g., `Interface1`) are arbitrary and are not used. -The `locations` field is optional and its default value is `faceCenters` (with `faceCentres` also accepted), signifying that the interface mesh is defined on the cell face centers. The alternative option is `faceNodes`, which defines the mesh on the face nodes and is needed e.g. for reading displacements in an FSI scenario. +The `locations` field is optional and its default value is `faceCenters` (with `faceCentres` also accepted), signifying that the interface mesh is defined on the cell face centers. The alternative option is `faceNodes`, which defines the mesh on the face nodes and is needed, e.g., for reading displacements in an FSI scenario. The values for `readData` and `writeData` for conjugate heat transfer can be `Temperature`, `Heat-Flux`, `Sink-Temperature`, -or `Heat-Transfer-Coefficient`. Values like `Sink-Temperature-Domain1` are also allowed. +or `Heat-Transfer-Coefficient`. Postfixed names like `Sink-Temperature-Domain1` are also allowed (e.g., in order to distinguish multiple data sets of the same type). For a Dirichlet-Neumann coupling, the `writeData` and `readData` can be either: @@ -109,18 +109,25 @@ For a Robin-Robin coupling, we need to write and read both of `Sink-Temperature` ```c++ readData ( - Sink-Temperature // e.g. Sink-Temperature-Solid - Heat-Transfer-Coefficient // e.g. Heat-Transfer-Coefficient-Solid + Sink-Temperature // e.g., Sink-Temperature-Solid + Heat-Transfer-Coefficient // e.g., Heat-Transfer-Coefficient-Solid ); writeData ( - Sink-Temperature // e.g. Sink-Temperature-Fluid - Heat-Transfer-Coefficient // e.g. Heat-Transfer-Coefficient-Fluid + Sink-Temperature // e.g., Sink-Temperature-Fluid + Heat-Transfer-Coefficient // e.g., Heat-Transfer-Coefficient-Fluid ); ``` -For fluid-structure interaction, `writeData` can be `Force` or `Stress`, where `Stress` is essentially a force vector scaled by the cell face in spatial coordinates (with any postfix), thus, a conservative quantity as well. `readData` can be `Displacement` and `DisplacementDelta` (with any postfix). `DisplacementDelta` refers to the last coupling time step, which needs to considered in the case of subcycling. Structure solvers (such as solids4Foam) can also write `Displacement` and read `Force`. +For fluid-structure interaction, coupled quantities can be: + +- `writeData`: + - fluid participants: `Force`, `Stress` (force over area, consistent) + - solid participants: `Displacement` +- `readData`: + - fluid participants: `Displacement`, `DisplacementDelta` (difference to the displacement at the last coupling time window) + - solid participants: `Force`, `Stress` {% warning %} You will run into problems when you use `Displacement(Delta)` as write data set and execute RBF mappings in parallel. This would affect users who use OpenFOAM and the adapter as the Solid participant in order to compute solid mechanics with OpenFOAM (currently not officially supported at all). Have a look [at this issue on GitHub](https://github.com/precice/openfoam-adapter/issues/153) for details. @@ -139,9 +146,9 @@ Read the [OpenFOAM User Guide](https://www.openfoam.com/documentation/user-guide #### CHT -* For `readData(Temperature)`, use `type fixedValue` for the `interface` in `0/T`. +- For `readData(Temperature)`, use `type fixedValue` for the `interface` in `0/T`. OpenFOAM requires that you also give a (redundant) `value`, but the adapter -will overwrite it. ParaView uses this value for the initial time. As a placeholder, you can e.g. use the value from the `internalField`. +will overwrite it. ParaView uses this value for the initial time. As a placeholder, you can, e.g., use the value from the `internalField`. ```c++ interface @@ -151,7 +158,7 @@ interface } ``` -* For `readData(Heat-Flux)`, use `type fixedGradient` for the `interface` in `0/T`. +- For `readData(Heat-Flux)`, use `type fixedGradient` for the `interface` in `0/T`. OpenFOAM requires that you also give a (redundant) `gradient`, but the adapter will overwrite it. ```c++ @@ -162,7 +169,7 @@ interface } ``` -* For `readData(Sink-Temperature)` or `Heat-Transfer-Coefficient`, use +- For `readData(Sink-Temperature)` or `Heat-Transfer-Coefficient`, use `type mixed` for the `interface` in `0/T`. OpenFOAM requires that you also give (redundant) values for `refValue`, `refGradient`, and `valueFraction`, but the adapter will overwrite them. @@ -178,10 +185,10 @@ interface #### FSI -* For `readData(Displacement)` or `DisplacementDelta`, you need the following: - * `type movingWallVelocity` for the interface (e.g. `flap`) in `0/U`, - * `type fixedValue` for the interface (e.g. `flap`) in the `0/pointDisplacement`, and - * `solver displacementLaplacian` in the `constant/dynamicMeshDict`. The solver [`RBFMeshMotionSolver` from solids4foam is also known to work](https://github.com/precice/openfoam-adapter/pull/241), currently (August 2022) with the develop branch of the OpenFOAM adapter and the nextRelease branch of solids4foam. +- For `readData(Displacement)` or `DisplacementDelta`, you need the following: + - `type movingWallVelocity` for the interface (e.g., `flap`) in `0/U`, + - `type fixedValue` for the interface (e.g., `flap`) in the `0/pointDisplacement`, and + - `solver displacementLaplacian` in the `constant/dynamicMeshDict`. The solver [`RBFMeshMotionSolver` from solids4foam is also known to work](https://github.com/precice/openfoam-adapter/pull/241), since the OpenFOAM adapter v1.2.0 and the [`nextRelease` branch (v2) of solids4foam](https://github.com/solids4foam/solids4foam/commit/971d4c08f0171cfd8d53a6f831ce0745d98521de). ```c++ // File 0/U @@ -204,6 +211,17 @@ motionSolverLibs ("libfvMotionSolvers.so"); solver displacementLaplacian; ``` +#### FF + +The fluid-fluid coupling module supports reading and writing `Pressure`, `Velocity`, `PressureGradient`, and `VelocityGradient`. + +Similarly to the CHT module, you need a `fixedValue` boundary condition of the respective primary field in order to read and apply values, and a `fixedGradient` boundary condition of the respective gradient field in order to read and apply gradients. + +{% experimental %} +The FF module is still experimental and the boundary conditions presented here have not been rigorously tested. +We already have reasons to believe that a `fixedGradient` can have [side-effects](https://github.com/precice/openfoam-adapter/issues/93) and may not lead to completely accurate results. +{% endexperimental %} + ### Load the adapter To load this adapter, you must include the following in @@ -230,7 +248,7 @@ If you are using other function objects in your simulation, add the preCICE adap ## Advanced configuration -These additional parameters may only concern some users is special cases. Keep reading if you want to use nearest-projection mapping, an incompressible or basic (e.g. laplacianFoam) solver, if you are using a solver with different variable names (e.g. a multiphase solver) or if you are trying to debug a simulation. +These additional parameters may only concern some users in special cases. Keep reading if you want to use the nearest-projection mapping, an incompressible or basic (e.g., laplacianFoam) solver, if you are using a solver with different variable names (e.g., a multiphase solver) or if you are trying to debug a simulation. ### Nearest-projection mapping @@ -352,7 +370,18 @@ FSI } ``` -This will force the adapter use the boundary condition implementations +Note that the adapter [does not currently adapt the name of the pressure used in the computations for compressible solvers](https://github.com/precice/openfoam-adapter/issues/253). + +For an FF simulation, known types are `incompressible` and `compressible`: + +```c++ +FF +{ + solverType incompressible; +} +``` + +This will force the adapter to use the boundary condition implementations for the respective type. #### Parameters and fields with different names @@ -395,10 +424,21 @@ FSI Use the option `namePointDisplacement unused;` for solvers that do not create a pointDisplacement field, such as the RBFMeshMotionSolver. -#### Debugging +For FF simulations: -The adapter also recognizes a few more parameters, which are mainly used in debugging or development. -These are optional and expect a `true` or a `false` value. Some or all of these options may be removed in the future. +```c++ +FF +{ + // Velocity + nameU U; + // Pressure + nameP p; +} +``` + +Note that the adapter does not automatically adapt the pressure name for solvers that account for [hydrostatic pressure effects](https://www.openfoam.com/documentation/guides/latest/doc/guide-applications-solvers-variable-transform-p-rgh.html). In these cases, you may want to set `nameP p_rgh` to couple `p_rgh`, as `p` is a derived quantity for these solvers. + +#### Debugging The user can toggle debug messages at [build time](https://precice.org/adapter-openfoam-get.html). From 154eb718c4708e3f65dcc3a077741314b123bcd1 Mon Sep 17 00:00:00 2001 From: David Schneider Date: Wed, 5 Oct 2022 11:30:29 +0200 Subject: [PATCH 23/31] Implement restart from reference configuration (#224) * Implement a checkpoint reset functionality * Add more comments in the code as suggested in the review * Add documentation for the new option * Rename variable to restartFromDeformed * Restrict option to fluid solvers Co-authored-by: Gerasimos Chourdakis --- Adapter.C | 6 ++++- FSI/FSI.C | 30 +++++++++++++++++++++ FSI/FSI.H | 12 +++++++++ Interface.C | 57 +++++++++++++++++++++++++++++++++++----- Interface.H | 13 +++++++-- changelog-entries/224.md | 1 + docs/config.md | 16 +++++++++++ 7 files changed, 125 insertions(+), 10 deletions(-) create mode 100644 changelog-entries/224.md diff --git a/Adapter.C b/Adapter.C index 238ff4ab..d8e81373 100644 --- a/Adapter.C +++ b/Adapter.C @@ -249,7 +249,11 @@ void preciceAdapter::Adapter::configure() DEBUG(adapterInfo("Creating interfaces...")); for (uint i = 0; i < interfacesConfig_.size(); i++) { - Interface* interface = new Interface(*precice_, mesh_, interfacesConfig_.at(i).meshName, interfacesConfig_.at(i).locationsType, interfacesConfig_.at(i).patchNames, interfacesConfig_.at(i).meshConnectivity); + std::string namePointDisplacement = FSIenabled_ ? FSI_->getPointDisplacementFieldName() : "default"; + std::string nameCellDisplacement = FSIenabled_ ? FSI_->getCellDisplacementFieldName() : "default"; + bool restartFromDeformed = FSIenabled_ ? FSI_->isRestartingFromDeformed() : false; + + Interface* interface = new Interface(*precice_, mesh_, interfacesConfig_.at(i).meshName, interfacesConfig_.at(i).locationsType, interfacesConfig_.at(i).patchNames, interfacesConfig_.at(i).meshConnectivity, restartFromDeformed, namePointDisplacement, nameCellDisplacement); interfaces_.push_back(interface); DEBUG(adapterInfo("Interface created on mesh " + interfacesConfig_.at(i).meshName)); diff --git a/FSI/FSI.C b/FSI/FSI.C index 5050bb31..6525735f 100644 --- a/FSI/FSI.C +++ b/FSI/FSI.C @@ -55,6 +55,21 @@ bool preciceAdapter::FSI::FluidStructureInteraction::readConfig(const IOdictiona solverType_ = FSIdict.lookupOrDefault("solverType", ""); DEBUG(adapterInfo(" user-defined solver type : " + solverType_)); + // When restarting FSI simulations, we may need to account for previous displacement. + // We do this by resetting the displacement when defining the interface. + // Since this is a feature that may not work as expected, depending on the implementation of the + // structure solver used, we make this feature opt-in. + restartFromDeformed_ = FSIdict.lookupOrDefault("restartFromDeformed", true); + + if (solverType_ == "solid" && !restartFromDeformed_) + { + adapterInfo("The option \"restartFromDeformed\" is only valid for Fluid solvers. Solid solvers usually use exclusively the reference configuration for computations and the mesh is not deforming over time.", "error"); + } + + if (solverType_ != "solid") + { + DEBUG(adapterInfo(" restart from deformed : " + std::to_string(restartFromDeformed_))); + } /* TODO: Read the names of any needed fields and parameters. * Include the force here? */ @@ -210,3 +225,18 @@ bool preciceAdapter::FSI::FluidStructureInteraction::addReaders(std::string data return found; } + +std::string preciceAdapter::FSI::FluidStructureInteraction::getCellDisplacementFieldName() +{ + return nameCellDisplacement_; +} + +std::string preciceAdapter::FSI::FluidStructureInteraction::getPointDisplacementFieldName() +{ + return namePointDisplacement_; +} + +bool preciceAdapter::FSI::FluidStructureInteraction::isRestartingFromDeformed() +{ + return restartFromDeformed_; +} diff --git a/FSI/FSI.H b/FSI/FSI.H index 008da0a6..a8d364b5 100644 --- a/FSI/FSI.H +++ b/FSI/FSI.H @@ -28,6 +28,9 @@ protected: //- Solver type std::string solverType_ = "none"; + //- Restart a simulation from an undeformed or a deformed interface + bool restartFromDeformed_; + //- Name of the pointDisplacement field std::string namePointDisplacement_ = "pointDisplacement"; @@ -63,6 +66,15 @@ public: //- Add coupling data readers bool addReaders(std::string dataName, Interface* interface); + + //- Return the nameCellDisplacement_ field name + std::string getCellDisplacementFieldName(); + + //- Return the namePointDisplacement_ field name + std::string getPointDisplacementFieldName(); + + //- Return the boolean variable stored in the class + bool isRestartingFromDeformed(); }; } diff --git a/Interface.C b/Interface.C index 502c6339..694f2b54 100644 --- a/Interface.C +++ b/Interface.C @@ -11,11 +11,15 @@ preciceAdapter::Interface::Interface( std::string meshName, std::string locationsType, std::vector patchNames, - bool meshConnectivity) + bool meshConnectivity, + bool restartFromDeformed, + const std::string& namePointDisplacement, + const std::string& nameCellDisplacement) : precice_(precice), meshName_(meshName), patchNames_(patchNames), - meshConnectivity_(meshConnectivity) + meshConnectivity_(meshConnectivity), + restartFromDeformed_(restartFromDeformed) { // Get the meshID from preCICE meshID_ = precice_.getMeshID(meshName_); @@ -68,10 +72,10 @@ preciceAdapter::Interface::Interface( } // Configure the mesh (set the data locations) - configureMesh(mesh); + configureMesh(mesh, namePointDisplacement, nameCellDisplacement); } -void preciceAdapter::Interface::configureMesh(const fvMesh& mesh) +void preciceAdapter::Interface::configureMesh(const fvMesh& mesh, const std::string& namePointDisplacement, const std::string& nameCellDisplacement) { // The way we configure the mesh differs between meshes based on face centers // and meshes based on face nodes. @@ -88,6 +92,12 @@ void preciceAdapter::Interface::configureMesh(const fvMesh& mesh) } DEBUG(adapterInfo("Number of face centres: " + std::to_string(numDataLocations_))); + // In case we want to perform the reset later on, look-up the corresponding data field name + Foam::volVectorField const* cellDisplacement = nullptr; + if (mesh.foundObject(nameCellDisplacement)) + cellDisplacement = + &mesh.lookupObject(nameCellDisplacement); + // Array of the mesh vertices. // One mesh is used for all the patches and each vertex has 3D coordinates. double vertices[dim_ * numDataLocations_]; @@ -104,9 +114,16 @@ void preciceAdapter::Interface::configureMesh(const fvMesh& mesh) for (uint j = 0; j < patchIDs_.size(); j++) { // Get the face centers of the current patch - const vectorField faceCenters = + vectorField faceCenters = mesh.boundaryMesh()[patchIDs_.at(j)].faceCentres(); + // Move the interface according to the current values of the cellDisplacement field, + // to account for any displacements accumulated before restarting the simulation. + // This is information that OpenFOAM reads from its result/restart files. + // If the simulation is not restarted, the displacement should be zero and this line should have no effect. + if (cellDisplacement != nullptr && !restartFromDeformed_) + faceCenters -= cellDisplacement->boundaryField()[patchIDs_.at(j)]; + // Assign the (x,y,z) locations to the vertices for (int i = 0; i < faceCenters.size(); i++) for (unsigned int d = 0; d < dim_; ++d) @@ -176,6 +193,12 @@ void preciceAdapter::Interface::configureMesh(const fvMesh& mesh) } DEBUG(adapterInfo("Number of face nodes: " + std::to_string(numDataLocations_))); + // In case we want to perform the reset later on, look-up the corresponding data field name + Foam::pointVectorField const* pointDisplacement = nullptr; + if (mesh.foundObject(namePointDisplacement)) + pointDisplacement = + &mesh.lookupObject(namePointDisplacement); + // Array of the mesh vertices. // One mesh is used for all the patches and each vertex has 3D coordinates. double vertices[dim_ * numDataLocations_]; @@ -196,9 +219,21 @@ void preciceAdapter::Interface::configureMesh(const fvMesh& mesh) // TODO: Check if this behaves correctly in parallel. // TODO: Check if this behaves correctly with multiple, connected patches. // TODO: Maybe this should be a pointVectorField? - const pointField faceNodes = + pointField faceNodes = mesh.boundaryMesh()[patchIDs_.at(j)].localPoints(); + // Similar to the cell displacement above: + // Move the interface according to the current values of the cellDisplacement field, + // to account for any displacements accumulated before restarting the simulation. + // This is information that OpenFOAM reads from its result/restart files. + // If the simulation is not restarted, the displacement should be zero and this line should have no effect. + if (pointDisplacement != nullptr && !restartFromDeformed_) + { + const vectorField& resetField = refCast( + pointDisplacement->boundaryField()[patchIDs_.at(j)]); + faceNodes -= resetField; + } + // Assign the (x,y,z) locations to the vertices // TODO: Ensure consistent order when writing/reading for (int i = 0; i < faceNodes.size(); i++) @@ -235,7 +270,15 @@ void preciceAdapter::Interface::configureMesh(const fvMesh& mesh) // Get the list of faces and coordinates at the interface patch const List faceField = mesh.boundaryMesh()[patchIDs_.at(j)].localFaces(); - const Field pointCoords = mesh.boundaryMesh()[patchIDs_.at(j)].localPoints(); + Field pointCoords = mesh.boundaryMesh()[patchIDs_.at(j)].localPoints(); + + // Subtract the displacement part in case we have deformation + if (pointDisplacement != nullptr && !restartFromDeformed_) + { + const vectorField& resetField = refCast( + pointDisplacement->boundaryField()[patchIDs_.at(j)]); + pointCoords -= resetField; + } // Array to store coordinates in preCICE format double triCoords[faceField.size() * triaPerQuad * nodesPerTria * componentsPerNode]; diff --git a/Interface.H b/Interface.H index bc18134a..3d05329e 100644 --- a/Interface.H +++ b/Interface.H @@ -7,6 +7,7 @@ #include "CouplingDataUser.H" #include "precice/SolverInterface.hpp" +#include "pointPatchField.H" namespace preciceAdapter { @@ -50,12 +51,17 @@ protected: //Switch for faceTriangulation (nearest projection) bool meshConnectivity_; + //- Reset the displacement during interface definition + bool restartFromDeformed_; + // Simulation dimension unsigned int dim_; //- Extracts the locations of the face centers or face nodes // and exposes them to preCICE with setMeshVertices - void configureMesh(const Foam::fvMesh& mesh); + void configureMesh(const Foam::fvMesh& mesh, + const std::string& namePointDisplacement, + const std::string& nameCellDisplacement); public: //- Constructor @@ -65,7 +71,10 @@ public: std::string meshName, std::string locationsType, std::vector patchNames, - bool meshConnectivity); + bool meshConnectivity, + bool restartFromDeformed, + const std::string& namePointDisplacement, + const std::string& nameCellDisplacement); //- Add a CouplingDataUser to read data from the interface void addCouplingDataReader( diff --git a/changelog-entries/224.md b/changelog-entries/224.md new file mode 100644 index 00000000..aa5bb785 --- /dev/null +++ b/changelog-entries/224.md @@ -0,0 +1 @@ +- Added support for a restart from the initial undeformed interface mesh for Fluid solvers in FSI simulations [#224](https://github.com/precice/openfoam-adapter/pull/224). diff --git a/docs/config.md b/docs/config.md index aa37c08a..58eff015 100644 --- a/docs/config.md +++ b/docs/config.md @@ -438,6 +438,22 @@ FF Note that the adapter does not automatically adapt the pressure name for solvers that account for [hydrostatic pressure effects](https://www.openfoam.com/documentation/guides/latest/doc/guide-applications-solvers-variable-transform-p-rgh.html). In these cases, you may want to set `nameP p_rgh` to couple `p_rgh`, as `p` is a derived quantity for these solvers. +#### Restarting FSI simulations + +Restarting a coupled simulation using the OpenFOAM adapter works in principle in the same way as restarting a standalone OpenFOAM solver. However, the adapter and preCICE define the coupling interface and the interface node locations based on the mesh at the particular time. In case of FSI simulations, the interface deforms over time, which leads to the definition of a deformed interface during the restart. The boolean variable `restartFromDeformed` (`true` by default) allows to account for the previously accumulated interface deformation such that the initial interface configuration (`t = 0`) is completely recovered. The setting here needs to agree with the behavior of the selected solid solver. + +```c++ +FSI +{ + // Account for previous displacement during a restart + restartFromDeformed true; +} +``` + +{% important %} +The option here defines the way the interface mesh is initialized when restarting an FSI simulation in OpenFOAM. In order to restart a coupled simulation, your solid solver needs to be capable of restarting as well. Furthermore, the two participants need to follow the same assumption for the initialization, which for OpenFOAM you can configure with this option. You can find more information about restarting coupled simulations on [Dsicourse](https://precice.discourse.group/t/how-can-i-restart-a-coupled-simulation/675). +{% endimportant %} + #### Debugging The user can toggle debug messages at [build time](https://precice.org/adapter-openfoam-get.html). From 552c882deb4767d15bcc85da004444b213aa32bb Mon Sep 17 00:00:00 2001 From: Gerasimos Chourdakis Date: Mon, 24 Oct 2022 16:09:01 +0200 Subject: [PATCH 24/31] Generalize solidForce to Force (#252) --- FSI/FSI.C | 10 +++++----- FSI/FSI.H | 4 ++-- FSI/Force.C | 39 ++++++++++++++++++++------------------- FSI/Force.H | 5 +---- docs/config.md | 4 ++-- 5 files changed, 30 insertions(+), 32 deletions(-) diff --git a/FSI/FSI.C b/FSI/FSI.C index 6525735f..0681896f 100644 --- a/FSI/FSI.C +++ b/FSI/FSI.C @@ -82,9 +82,9 @@ bool preciceAdapter::FSI::FluidStructureInteraction::readConfig(const IOdictiona nameCellDisplacement_ = FSIdict.lookupOrDefault("nameCellDisplacement", "cellDisplacement"); DEBUG(adapterInfo(" cellDisplacement field name : " + nameCellDisplacement_)); - // Read the name of the solidForce field (if different) - nameSolidForce_ = FSIdict.lookupOrDefault("nameSolidForce", "solidForce"); - DEBUG(adapterInfo(" solidForce field name : " + nameSolidForce_)); + // Read the name of the force field (if different) + nameForce_ = FSIdict.lookupOrDefault("nameForce", "Force"); + DEBUG(adapterInfo(" force field name : " + nameForce_)); return true; } @@ -138,7 +138,7 @@ bool preciceAdapter::FSI::FluidStructureInteraction::addWriters(std::string data { interface->addCouplingDataWriter( dataName, - new Force(mesh_, solverType_, nameSolidForce_) /* TODO: Add any other arguments here */ + new Force(mesh_, solverType_, nameForce_) /* TODO: Add any other arguments here */ ); DEBUG(adapterInfo("Added writer: Force.")); } @@ -186,7 +186,7 @@ bool preciceAdapter::FSI::FluidStructureInteraction::addReaders(std::string data { interface->addCouplingDataReader( dataName, - new Force(mesh_, solverType_, nameSolidForce_) /* TODO: Add any other arguments here */ + new Force(mesh_, solverType_, nameForce_) /* TODO: Add any other arguments here */ ); DEBUG(adapterInfo("Added reader: Force.")); } diff --git a/FSI/FSI.H b/FSI/FSI.H index a8d364b5..52d948fa 100644 --- a/FSI/FSI.H +++ b/FSI/FSI.H @@ -37,8 +37,8 @@ protected: //- Name of the pointDisplacement field std::string nameCellDisplacement_ = "cellDisplacement"; - //- Name of the force field used by the solid - std::string nameSolidForce_ = "solidForce"; + //- Name of the force field + std::string nameForce_ = "Force"; /* TODO: Declare here any parameters that should be read from / the configuration file. See CHT/CHT.H for reference. diff --git a/FSI/Force.C b/FSI/Force.C index d2867f30..ed47a005 100644 --- a/FSI/Force.C +++ b/FSI/Force.C @@ -5,31 +5,32 @@ using namespace Foam; preciceAdapter::FSI::Force::Force( const Foam::fvMesh& mesh, const std::string solverType, - const std::string nameSolidForce) + const std::string nameForce) : ForceBase(mesh, solverType) { - Force_ = new volVectorField( - IOobject( - "Force", - mesh_.time().timeName(), - mesh, - IOobject::NO_READ, - IOobject::AUTO_WRITE), - mesh, - dimensionedVector( - "fdim", - dimensionSet(1, 1, -2, 0, 0, 0, 0), - Foam::vector::zero)); - - if (mesh_.foundObject(nameSolidForce)) + // Check if a force field with the requested name exists. + // If yes (e.g., solids4Foam), bind Force_ to that field. + // If not (e.g., pimpleFoam without the Forces function object), create it. + if (mesh_.foundObject(nameForce)) { - solidForce_ = + Force_ = &const_cast( - mesh_.lookupObject(nameSolidForce)); + mesh_.lookupObject(nameForce)); } else { - solidForce_ = nullptr; + Force_ = new volVectorField( + IOobject( + nameForce, + mesh_.time().timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE), + mesh, + dimensionedVector( + "fdim", + dimensionSet(1, 1, -2, 0, 0, 0, 0), + Foam::vector::zero)); } } @@ -54,7 +55,7 @@ void preciceAdapter::FSI::Force::read(double* buffer, const unsigned int dim) if (this->locationType_ == LocationType::faceCenters) { // Make a force field - vectorField& force = solidForce_->boundaryFieldRef()[patchID]; + vectorField& force = Force_->boundaryFieldRef()[patchID]; // Copy the forces from the buffer into the force field forAll(force, i) diff --git a/FSI/Force.H b/FSI/Force.H index 268b2ee3..38bbb1a8 100644 --- a/FSI/Force.H +++ b/FSI/Force.H @@ -15,15 +15,12 @@ private: //- Force field Foam::volVectorField* Force_; - //- Solid force field - Foam::volVectorField* solidForce_; - public: //- Constructor Force( const Foam::fvMesh& mesh, const std::string solverType, - const std::string nameSolidForce); + const std::string nameForce); //- Write the forces values into the buffer void write(double* buffer, bool meshConnectivity, const unsigned int dim) final; diff --git a/docs/config.md b/docs/config.md index 58eff015..1dad4983 100644 --- a/docs/config.md +++ b/docs/config.md @@ -417,8 +417,8 @@ FSI // Displacement fields namePointDisplacement pointD; nameCellDisplacement D; - // Force field on the solid - forceFieldName solidForce; + // Force field + nameForce Force; // For solids4Foam: solidForce } ``` From a4e6f8290ddf7a6d62ba148e7475bb1052cf55d0 Mon Sep 17 00:00:00 2001 From: Gerasimos Chourdakis Date: Mon, 14 Nov 2022 09:38:52 +0100 Subject: [PATCH 25/31] Prepare Changelog for v1.2.0 --- CHANGELOG.md | 19 ++++++++++++++++++- changelog-entries/220.md | 1 - changelog-entries/224.md | 1 - changelog-entries/230.md | 1 - changelog-entries/236.md | 1 - changelog-entries/241.md | 1 - changelog-entries/244.md | 1 - changelog-entries/245.md | 1 - changelog-entries/246.md | 1 - changelog-entries/247.md | 1 - changelog-entries/254.md | 1 - 11 files changed, 18 insertions(+), 11 deletions(-) delete mode 100644 changelog-entries/220.md delete mode 100644 changelog-entries/224.md delete mode 100644 changelog-entries/230.md delete mode 100644 changelog-entries/236.md delete mode 100644 changelog-entries/241.md delete mode 100644 changelog-entries/244.md delete mode 100644 changelog-entries/245.md delete mode 100644 changelog-entries/246.md delete mode 100644 changelog-entries/247.md delete mode 100644 changelog-entries/254.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 63510b7d..1090145e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,10 +8,27 @@ Read more details in the issue [#52: Releases and versioning](https://github.com -## [Unreleased] +## [v1.2.0] 2022-11-14 + +### Added + +- Added support for a restart from the initial undeformed interface mesh for Fluid solvers in FSI simulations [#224](https://github.com/precice/openfoam-adapter/pull/224). +- Added functionality to allow use of solids4foam with the OpenFOAM adapter. +- Enabled mesh motion solvers that do not register a pointDisplacement field (such as the RBFMeshMotionSolver from solids4foam) to work with the adapter [#241](https://github.com/precice/openfoam-adapter/pull/241) +- Added a warning for trying to build without pkg-config being available and more suggestions for possible problems [#220](https://github.com/precice/openfoam-adapter/pull/220). +- Added more documentation, specifically for configuring the FF module. [#254](https://github.com/precice/openfoam-adapter/pull/254) ### Changed +- Removed the default `-j 4` option from the wmake command. Instead, documented the `WM_NCOMPPROCS` option of OpenFOAM. [#244](https://github.com/precice/openfoam-adapter/pull/244) +- Changed virtual function declarations to explicitly define one (only) of virtual/override/final. If you need to extend a method marked as `final`, please report. [#245](https://github.com/precice/openfoam-adapter/pull/245) +- Changed the xy-plane error to a warning, to support 2D axisymmetric cases. [#246](https://github.com/precice/openfoam-adapter/pull/246) +- OpenFOAM version bumped to v2206 in GitHub Actions (including preCICE v2.3.0 --> v2.4.0) and documentation [#230](https://github.com/precice/openfoam-adapter/pull/230). + +### Removed + +- Removed the (deprecated since preCICE v2.5.0) call to isReadDataAvailable. [#247](https://github.com/precice/openfoam-adapter/pull/247) + ## [v1.1.0] 2022-02-08 ### Added diff --git a/changelog-entries/220.md b/changelog-entries/220.md deleted file mode 100644 index ff26bc30..00000000 --- a/changelog-entries/220.md +++ /dev/null @@ -1 +0,0 @@ -- Added a warning for trying to build without pkg-config being available and more suggestions for possible problems [#220](https://github.com/precice/openfoam-adapter/pull/220). diff --git a/changelog-entries/224.md b/changelog-entries/224.md deleted file mode 100644 index aa5bb785..00000000 --- a/changelog-entries/224.md +++ /dev/null @@ -1 +0,0 @@ -- Added support for a restart from the initial undeformed interface mesh for Fluid solvers in FSI simulations [#224](https://github.com/precice/openfoam-adapter/pull/224). diff --git a/changelog-entries/230.md b/changelog-entries/230.md deleted file mode 100644 index a4c3d0f5..00000000 --- a/changelog-entries/230.md +++ /dev/null @@ -1 +0,0 @@ -- OpenFOAM version bumped to v2206 in GitHub Actions (including preCICE v2.3.0 --> v2.4.0) and documentation [#230](https://github.com/precice/openfoam-adapter/pull/230). diff --git a/changelog-entries/236.md b/changelog-entries/236.md deleted file mode 100644 index e80f533f..00000000 --- a/changelog-entries/236.md +++ /dev/null @@ -1 +0,0 @@ -- Added functionality to allow use of solids4foam with the OpenFOAM adapter diff --git a/changelog-entries/241.md b/changelog-entries/241.md deleted file mode 100644 index 2072005a..00000000 --- a/changelog-entries/241.md +++ /dev/null @@ -1 +0,0 @@ -- Enabled mesh motion solvers that do not register a pointDisplacement field (such as the RBFMeshMotionSolver from solids4foam) to work with the adapter [#241](https://github.com/precice/openfoam-adapter/pull/241) diff --git a/changelog-entries/244.md b/changelog-entries/244.md deleted file mode 100644 index 5c24afa9..00000000 --- a/changelog-entries/244.md +++ /dev/null @@ -1 +0,0 @@ -- Removed the default `-j 4` option from the wmake command. Instead, documented the `WM_NCOMPPROCS` option of OpenFOAM. [#244](https://github.com/precice/openfoam-adapter/pull/244) diff --git a/changelog-entries/245.md b/changelog-entries/245.md deleted file mode 100644 index 6e6fa6b6..00000000 --- a/changelog-entries/245.md +++ /dev/null @@ -1 +0,0 @@ -- Changed virtual function declarations to explicitly define one (only) of virtual/override/final. If you need to extend a method marked as `final`, please report. [#245](https://github.com/precice/openfoam-adapter/pull/245) diff --git a/changelog-entries/246.md b/changelog-entries/246.md deleted file mode 100644 index fc4af6bd..00000000 --- a/changelog-entries/246.md +++ /dev/null @@ -1 +0,0 @@ -- Changed the xy-plane error to a warning, to support 2D axisymmetric cases. [#246](https://github.com/precice/openfoam-adapter/pull/246) diff --git a/changelog-entries/247.md b/changelog-entries/247.md deleted file mode 100644 index 9d0625e1..00000000 --- a/changelog-entries/247.md +++ /dev/null @@ -1 +0,0 @@ -- Removed the (deprecated since preCICE v2.5.0) call to isReadDataAvailable. [#247](https://github.com/precice/openfoam-adapter/pull/247) diff --git a/changelog-entries/254.md b/changelog-entries/254.md deleted file mode 100644 index 99d64769..00000000 --- a/changelog-entries/254.md +++ /dev/null @@ -1 +0,0 @@ -- Added more documentation, specifically for configuring the FF module. [#254](https://github.com/precice/openfoam-adapter/pull/254) From cdaf6fb554df6b4a3ad327a12a2086716977bbc7 Mon Sep 17 00:00:00 2001 From: Gerasimos Chourdakis Date: Mon, 14 Nov 2022 17:45:08 +0100 Subject: [PATCH 26/31] Add timers (#256) Co-authored-by: David Schneider --- Adapter.C | 59 +++++++++++++++++++++++++++++++++- Adapter.H | 17 ++++++++++ Allwmake | 4 ++- Utilities.H | 26 +++++++++++++++ changelog-entries/256.md | 1 + docs/get.md | 4 ++- preciceAdapterFunctionObject.C | 50 ++++++++++++++++++++++++++++ preciceAdapterFunctionObject.H | 8 +++++ 8 files changed, 166 insertions(+), 3 deletions(-) create mode 100644 changelog-entries/256.md diff --git a/Adapter.C b/Adapter.C index d8e81373..697cd51a 100644 --- a/Adapter.C +++ b/Adapter.C @@ -23,6 +23,7 @@ bool preciceAdapter::Adapter::configFileRead() // See also comment in preciceAdapter::Adapter::configure(). try { + SETUP_TIMER(); adapterInfo("Reading preciceDict...", "info"); // TODO: static is just a quick workaround to be able @@ -195,6 +196,8 @@ bool preciceAdapter::Adapter::configFileRead() // TODO: Loading modules should be implemented in more general way, // in order to avoid code duplication. See issue #16 on GitHub. + + ACCUMULATE_TIMER(timeInConfigRead_); } catch (const Foam::error& e) { @@ -238,14 +241,18 @@ void preciceAdapter::Adapter::configure() DEBUG(adapterInfo(" Timestep type: fixed.")); } - // Initialize preCICE + // Construct preCICE + SETUP_TIMER(); DEBUG(adapterInfo("Creating the preCICE solver interface...")); DEBUG(adapterInfo(" Number of processes: " + std::to_string(Pstream::nProcs()))); DEBUG(adapterInfo(" MPI rank: " + std::to_string(Pstream::myProcNo()))); precice_ = new precice::SolverInterface(participantName_, preciceConfigFilename_, Pstream::myProcNo(), Pstream::nProcs()); DEBUG(adapterInfo(" preCICE solver interface was created.")); + ACCUMULATE_TIMER(timeInPreciceConstruct_); + // Create interfaces + REUSE_TIMER(); DEBUG(adapterInfo("Creating interfaces...")); for (uint i = 0; i < interfacesConfig_.size(); i++) { @@ -333,6 +340,7 @@ void preciceAdapter::Adapter::configure() // Create the interface's data buffer interface->createBuffer(); } + ACCUMULATE_TIMER(timeInMeshSetup_); // Initialize preCICE and exchange the first coupling data initialize(); @@ -437,6 +445,7 @@ void preciceAdapter::Adapter::execute() // coupling, we write again when the coupling timestep is complete. // Check the behavior e.g. by using watch on a result file: // watch -n 0.1 -d ls --full-time Fluid/0.01/T.gz + SETUP_TIMER(); if (checkpointing_ && isCouplingTimeWindowComplete()) { // Check if the time directory already exists @@ -450,6 +459,7 @@ void preciceAdapter::Adapter::execute() const_cast(runTime_).writeNow(); } } + ACCUMULATE_TIMER(timeInWriteResults_); // Read the received coupling data from the buffer readCouplingData(); @@ -490,6 +500,7 @@ void preciceAdapter::Adapter::adjustTimeStep() void preciceAdapter::Adapter::readCouplingData() { + SETUP_TIMER(); DEBUG(adapterInfo("Reading coupling data...")); for (uint i = 0; i < interfaces_.size(); i++) @@ -497,11 +508,14 @@ void preciceAdapter::Adapter::readCouplingData() interfaces_.at(i)->readCouplingData(); } + ACCUMULATE_TIMER(timeInRead_); + return; } void preciceAdapter::Adapter::writeCouplingData() { + SETUP_TIMER(); DEBUG(adapterInfo("Writing coupling data...")); for (uint i = 0; i < interfaces_.size(); i++) @@ -509,13 +523,17 @@ void preciceAdapter::Adapter::writeCouplingData() interfaces_.at(i)->writeCouplingData(); } + ACCUMULATE_TIMER(timeInWrite_); + return; } void preciceAdapter::Adapter::initialize() { DEBUG(adapterInfo("Initializing the preCICE solver interface...")); + SETUP_TIMER(); timestepPrecice_ = precice_->initialize(); + ACCUMULATE_TIMER(timeInInitialize_); preciceInitialized_ = true; @@ -526,7 +544,9 @@ void preciceAdapter::Adapter::initialize() } DEBUG(adapterInfo("Initializing preCICE data...")); + REUSE_TIMER(); precice_->initializeData(); + ACCUMULATE_TIMER(timeInInitializeData_); adapterInfo("preCICE was configured and initialized", "info"); @@ -540,7 +560,9 @@ void preciceAdapter::Adapter::finalize() DEBUG(adapterInfo("Finalizing the preCICE solver interface...")); // Finalize the preCICE solver interface + SETUP_TIMER(); precice_->finalize(); + ACCUMULATE_TIMER(timeInFinalize_); preciceInitialized_ = false; @@ -559,7 +581,9 @@ void preciceAdapter::Adapter::advance() { DEBUG(adapterInfo("Advancing preCICE...")); + SETUP_TIMER(); timestepPrecice_ = precice_->advance(timestepSolver_); + ACCUMULATE_TIMER(timeInAdvance_); return; } @@ -865,6 +889,8 @@ void preciceAdapter::Adapter::setupMeshVolCheckpointing() void preciceAdapter::Adapter::setupCheckpointing() { + SETUP_TIMER(); + // Add fields in the checkpointing list - sorted for parallel consistency DEBUG(adapterInfo("Adding in checkpointed fields...")); @@ -893,6 +919,8 @@ void preciceAdapter::Adapter::setupCheckpointing() // NOTE: Add here other object types to checkpoint, if needed. #undef doLocalCode + + ACCUMULATE_TIMER(timeInCheckpointingSetup_); } @@ -1030,6 +1058,8 @@ void preciceAdapter::Adapter::addCheckpointField(volSymmTensorField* field) void preciceAdapter::Adapter::readCheckpoint() { + SETUP_TIMER(); + // TODO: To increase efficiency: only the oldTime() fields of the quantities which are used in the time // derivative are necessary. (In general this is only the velocity). Also old information of the mesh // is required. @@ -1220,12 +1250,16 @@ void preciceAdapter::Adapter::readCheckpoint() "Checkpoint was read. Time = " + std::to_string(runTime_.value())); #endif + ACCUMULATE_TIMER(timeInCheckpointingRead_); + return; } void preciceAdapter::Adapter::writeCheckpoint() { + SETUP_TIMER(); + DEBUG(adapterInfo("Writing a checkpoint...")); // Store the runTime @@ -1303,6 +1337,8 @@ void preciceAdapter::Adapter::writeCheckpoint() "Checkpoint for time t = " + std::to_string(runTime_.value()) + " was stored."); #endif + ACCUMULATE_TIMER(timeInCheckpointingWrite_); + return; } @@ -1612,5 +1648,26 @@ preciceAdapter::Adapter::~Adapter() { teardown(); + TIMING_MODE( + // Continuing the output started in the destructor of preciceAdapterFunctionObject + Info << "Time exclusively in the adapter: " << (timeInConfigRead_ + timeInMeshSetup_ + timeInCheckpointingSetup_ + timeInWrite_ + timeInRead_ + timeInCheckpointingWrite_ + timeInCheckpointingRead_).str() << nl; + Info << " (S) reading preciceDict: " << timeInConfigRead_.str() << nl; + Info << " (S) constructing preCICE: " << timeInPreciceConstruct_.str() << nl; + Info << " (S) setting up the interfaces: " << timeInMeshSetup_.str() << nl; + Info << " (S) setting up checkpointing: " << timeInCheckpointingSetup_.str() << nl; + Info << " (I) writing data: " << timeInWrite_.str() << nl; + Info << " (I) reading data: " << timeInRead_.str() << nl; + Info << " (I) writing checkpoints: " << timeInCheckpointingWrite_.str() << nl; + Info << " (I) reading checkpoints: " << timeInCheckpointingRead_.str() << nl; + Info << " (I) writing OpenFOAM results: " << timeInWriteResults_.str() << " (at the end of converged time windows)" << nl << nl; + Info << "Time exclusively in preCICE: " << (timeInInitialize_ + timeInInitializeData_ + timeInAdvance_ + timeInFinalize_).str() << nl; + Info << " (S) initialize(): " << timeInInitialize_.str() << nl; + Info << " (S) initializeData(): " << timeInInitializeData_.str() << nl; + Info << " (I) advance(): " << timeInAdvance_.str() << nl; + Info << " (I) finalize(): " << timeInFinalize_.str() << nl; + Info << " These times include time waiting for other participants." << nl; + Info << " See also precice--events-summary.log." << nl; + Info << "-------------------------------------------------------------------------------------" << nl;) + return; } diff --git a/Adapter.H b/Adapter.H index 41487151..f94fd9c5 100644 --- a/Adapter.H +++ b/Adapter.H @@ -48,6 +48,23 @@ private: //- Configuration interfaces std::vector interfacesConfig_; +#ifdef ADAPTER_ENABLE_TIMINGS + //- Timers + clockValue timeInConfigRead_; + clockValue timeInPreciceConstruct_; + clockValue timeInMeshSetup_; + clockValue timeInInitialize_; + clockValue timeInInitializeData_; + clockValue timeInCheckpointingSetup_; + clockValue timeInWrite_; + clockValue timeInAdvance_; + clockValue timeInRead_; + clockValue timeInCheckpointingRead_; + clockValue timeInCheckpointingWrite_; + clockValue timeInWriteResults_; + clockValue timeInFinalize_; +#endif + //- OpenFOAM runTime object const Foam::Time& runTime_; diff --git a/Allwmake b/Allwmake index 40b71ea6..371c0cb4 100755 --- a/Allwmake +++ b/Allwmake @@ -3,7 +3,9 @@ set -e -u ########## CONFIGURATION - You may want to change these ######################## -# Optional: Preprocessor flags ("-DADAPTER_DEBUG_MODE" enables debug messages) +# Optional: Preprocessor flags +# "-DADAPTER_DEBUG_MODE" enables debug messages +# "-DADAPTER_ENABLE_TIMINGS" enables time measurements ADAPTER_PREP_FLAGS="" # Build command and options diff --git a/Utilities.H b/Utilities.H index b3f3f797..8099d33d 100644 --- a/Utilities.H +++ b/Utilities.H @@ -8,6 +8,32 @@ #define DEBUG(x) #endif +// Filter-out timing when not required +#ifdef ADAPTER_ENABLE_TIMINGS +#define TIMING_MODE(x) x +#else +#define TIMING_MODE(x) +#endif + +// Shortcut for constructing clocks +#ifdef ADAPTER_ENABLE_TIMINGS +#define SETUP_TIMER() \ + clockValue clock; \ + clock.update() +#define REUSE_TIMER() clock.update() +#else +#define SETUP_TIMER() +#define REUSE_TIMER() +#endif + + +// Shortcut for adding time +#ifdef ADAPTER_ENABLE_TIMINGS +#define ACCUMULATE_TIMER(x) x += clock.elapsed() +#else +#define ACCUMULATE_TIMER(x) +#endif + // String added in the beginning of every printed message #define INFO_STR_ADAPTER "---[preciceAdapter] " diff --git a/changelog-entries/256.md b/changelog-entries/256.md new file mode 100644 index 00000000..66a4c980 --- /dev/null +++ b/changelog-entries/256.md @@ -0,0 +1 @@ +- Added timers for tracking the time spent in the adapter and preCICE [#256](https://github.com/precice/openfoam-adapter/pull/256). diff --git a/docs/get.md b/docs/get.md index 535ab09a..a9d32dd4 100644 --- a/docs/get.md +++ b/docs/get.md @@ -16,7 +16,9 @@ To build the adapter, you need to install a few dependencies and then execute th The adapter also requires [pkg-config](https://linux.die.net/man/1/pkg-config) to [link to preCICE](https://precice.org/installation-linking.html). This is a very common dependency on Linux and is usually already installed. -Adding `-DADAPTER_DEBUG_MODE` flag to the `ADAPTER_PREP_FLAGS` activates additional debug messages. You may also change the target directory or specify the number of threads to use for the compilation. See the comments in `Allwmake` for more. +Adding the `-DADAPTER_DEBUG_MODE` flag to the `ADAPTER_PREP_FLAGS` activates additional debug messages. You may also change the target directory or specify the number of threads to use for the compilation. See the comments in `Allwmake` for more. + +Adding the `-DADAPTER_ENABLE_TIMINGS` flag to the `ADAPTER_PREP_FLAGS` activates time measurements for several regions of the adapter, printed at the end of the simulation output (available since v1.2.0). If you are building the adapter often, you may want to build it in parallel. You can set the environment variable `WM_NCOMPPROCS` to the number of parallel threads you want WMake to use. diff --git a/preciceAdapterFunctionObject.C b/preciceAdapterFunctionObject.C index bc8e16a6..3dea534a 100644 --- a/preciceAdapterFunctionObject.C +++ b/preciceAdapterFunctionObject.C @@ -50,6 +50,7 @@ Foam::functionObjects::preciceAdapterFunctionObject::preciceAdapterFunctionObjec : fvMeshFunctionObject(name, runTime, dict), adapter_(runTime, mesh_) { + #if (defined OPENFOAM_PLUS && (OPENFOAM_PLUS >= 1712)) || (defined OPENFOAM && (OPENFOAM >= 1806)) // Patch for issue #27: warning "MPI was already finalized" while // running in serial. This only affects openfoam.com, while initNull() @@ -65,6 +66,12 @@ Foam::functionObjects::preciceAdapterFunctionObject::preciceAdapterFunctionObjec Foam::functionObjects::preciceAdapterFunctionObject::~preciceAdapterFunctionObject() { +#ifdef ADAPTER_ENABLE_TIMINGS + Info << "-------------------- preCICE adapter timers (primary rank) --------------------------" << nl; + Info << "Total time in adapter + preCICE: " << timeInAll_.str() << " (format: day-hh:mm:ss.ms)" << nl; + Info << " For setting up (S): " << timeInSetup_.str() << " (read() function)" << nl; + Info << " For all iterations (I): " << timeInExecute_.str() << " (execute() and adjustTimeStep() functions)" << nl << nl; +#endif } @@ -72,24 +79,57 @@ Foam::functionObjects::preciceAdapterFunctionObject::~preciceAdapterFunctionObje bool Foam::functionObjects::preciceAdapterFunctionObject::read(const dictionary& dict) { +#ifdef ADAPTER_ENABLE_TIMINGS + // Save the current wall clock time stamp to the clock + clockValue clock; + clock.update(); +#endif + adapter_.configure(); +#ifdef ADAPTER_ENABLE_TIMINGS + // Accumulate the time in this section into a global timer. + // Same in all function object methods. + timeInAll_ += clock.elapsed(); + timeInSetup_ = clock.elapsed(); +#endif + return true; } bool Foam::functionObjects::preciceAdapterFunctionObject::execute() { +#ifdef ADAPTER_ENABLE_TIMINGS + clockValue clock; + clock.update(); +#endif + adapter_.execute(); +#ifdef ADAPTER_ENABLE_TIMINGS + timeInAll_ += clock.elapsed(); + timeInExecute_ += clock.elapsed(); +#endif + return true; } bool Foam::functionObjects::preciceAdapterFunctionObject::end() { +#ifdef ADAPTER_ENABLE_TIMINGS + clockValue clock; + clock.update(); +#endif + adapter_.end(); +#ifdef ADAPTER_ENABLE_TIMINGS + timeInAll_ += clock.elapsed(); + timeInExecute_ += clock.elapsed(); +#endif + return true; } @@ -101,8 +141,18 @@ bool Foam::functionObjects::preciceAdapterFunctionObject::write() bool Foam::functionObjects::preciceAdapterFunctionObject::adjustTimeStep() { +#ifdef ADAPTER_ENABLE_TIMINGS + clockValue clock; + clock.update(); +#endif + adapter_.adjustTimeStep(); +#ifdef ADAPTER_ENABLE_TIMINGS + timeInAll_ += clock.elapsed(); + timeInExecute_ += clock.elapsed(); +#endif + return true; } diff --git a/preciceAdapterFunctionObject.H b/preciceAdapterFunctionObject.H index 63af7132..1cb8792f 100644 --- a/preciceAdapterFunctionObject.H +++ b/preciceAdapterFunctionObject.H @@ -59,6 +59,7 @@ SourceFiles // OpenFOAM header files #include "fvMeshFunctionObject.H" +#include "clockValue.H" // Main adapter header file #include "Adapter.H" @@ -79,6 +80,13 @@ class preciceAdapterFunctionObject { // Private data +#ifdef ADAPTER_ENABLE_TIMINGS + //- Cumulative time spent in the complete adapter function object (including preCICE calls) + clockValue timeInAll_; + clockValue timeInSetup_; + clockValue timeInExecute_; +#endif + //- Adapter's main class instance preciceAdapter::Adapter adapter_; From e84874ee116ff7c347027ebcef33a0515ac24c91 Mon Sep 17 00:00:00 2001 From: Gerasimos Chourdakis Date: Mon, 14 Nov 2022 17:51:39 +0100 Subject: [PATCH 27/31] Add timers to the changelog --- CHANGELOG.md | 1 + changelog-entries/256.md | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 changelog-entries/256.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 1090145e..5e72ca03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Read more details in the issue [#52: Releases and versioning](https://github.com - Added support for a restart from the initial undeformed interface mesh for Fluid solvers in FSI simulations [#224](https://github.com/precice/openfoam-adapter/pull/224). - Added functionality to allow use of solids4foam with the OpenFOAM adapter. - Enabled mesh motion solvers that do not register a pointDisplacement field (such as the RBFMeshMotionSolver from solids4foam) to work with the adapter [#241](https://github.com/precice/openfoam-adapter/pull/241) +- Added timers for tracking the time spent in the adapter and preCICE (disabled by default) [#256](https://github.com/precice/openfoam-adapter/pull/256). - Added a warning for trying to build without pkg-config being available and more suggestions for possible problems [#220](https://github.com/precice/openfoam-adapter/pull/220). - Added more documentation, specifically for configuring the FF module. [#254](https://github.com/precice/openfoam-adapter/pull/254) diff --git a/changelog-entries/256.md b/changelog-entries/256.md deleted file mode 100644 index 66a4c980..00000000 --- a/changelog-entries/256.md +++ /dev/null @@ -1 +0,0 @@ -- Added timers for tracking the time spent in the adapter and preCICE [#256](https://github.com/precice/openfoam-adapter/pull/256). From 9476d96c22d5d7b890b993988a581e6ba7e4dbfa Mon Sep 17 00:00:00 2001 From: Gerasimos Chourdakis Date: Wed, 16 Nov 2022 13:02:17 +0100 Subject: [PATCH 28/31] Force: Distinguish between owning and non-owning (#260) * Force: Distinguish between owning and non-owning Closes #259 --- FSI/Force.C | 11 ++++------- FSI/Force.H | 8 ++++---- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/FSI/Force.C b/FSI/Force.C index ed47a005..a51791db 100644 --- a/FSI/Force.C +++ b/FSI/Force.C @@ -19,7 +19,7 @@ preciceAdapter::FSI::Force::Force( } else { - Force_ = new volVectorField( + ForceOwning_ = std::make_unique(volVectorField( IOobject( nameForce, mesh_.time().timeName(), @@ -30,7 +30,9 @@ preciceAdapter::FSI::Force::Force( dimensionedVector( "fdim", dimensionSet(1, 1, -2, 0, 0, 0, 0), - Foam::vector::zero)); + Foam::vector::zero))); + + Force_ = ForceOwning_.get(); } } @@ -89,8 +91,3 @@ Foam::tmp preciceAdapter::FSI::Force::getFaceVectors(const un // Normal vectors multiplied by face area return mesh_.boundary()[patchID].Sf(); } - -preciceAdapter::FSI::Force::~Force() -{ - delete Force_; -} diff --git a/FSI/Force.H b/FSI/Force.H index 38bbb1a8..c528b14d 100644 --- a/FSI/Force.H +++ b/FSI/Force.H @@ -12,9 +12,12 @@ namespace FSI class Force : public ForceBase { private: - //- Force field + //- Force field (non-owning pointer, it may already be constructed by the solver) Foam::volVectorField* Force_; + //- Force field (owning pointer, we bind to Force_) + std::unique_ptr ForceOwning_; + public: //- Constructor Force( @@ -35,9 +38,6 @@ public: //- Returns the normal vectors multiplied by the face area Foam::tmp getFaceVectors(const unsigned int patchID) const final; - - //- Destructor - ~Force(); }; } From bc014b6e7b50c9e85813789d9100573d729c4d56 Mon Sep 17 00:00:00 2001 From: Gerasimos Chourdakis Date: Wed, 16 Nov 2022 17:35:39 +0100 Subject: [PATCH 29/31] Bump preCICE to v2.5.0 in the CI --- .github/workflows/install-dependencies.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/install-dependencies.sh b/.github/workflows/install-dependencies.sh index 27418e32..128c1b88 100755 --- a/.github/workflows/install-dependencies.sh +++ b/.github/workflows/install-dependencies.sh @@ -4,6 +4,6 @@ wget -q -O - https://dl.openfoam.com/add-debian-repo.sh | sudo bash sudo apt-get install openfoam2206-dev -# Install preCICE v2.4.0 -wget https://github.com/precice/precice/releases/download/v2.4.0/libprecice2_2.4.0_focal.deb -sudo apt install ./libprecice2_2.4.0_focal.deb +# Install preCICE v2.5.0 +wget https://github.com/precice/precice/releases/download/v2.5.0/libprecice2_2.5.0_focal.deb +sudo apt install ./libprecice2_2.5.0_focal.deb From 999a3aaa3f95d733ef588df3ad22ff48e7f80f4c Mon Sep 17 00:00:00 2001 From: Gerasimos Chourdakis Date: Wed, 16 Nov 2022 17:44:22 +0100 Subject: [PATCH 30/31] Update CHANGELOG.md --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e72ca03..b26d6da8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ Read more details in the issue [#52: Releases and versioning](https://github.com ### Added - Added support for a restart from the initial undeformed interface mesh for Fluid solvers in FSI simulations [#224](https://github.com/precice/openfoam-adapter/pull/224). -- Added functionality to allow use of solids4foam with the OpenFOAM adapter. +- Added functionality to allow use of solids4foam with the OpenFOAM adapter (new solver type "solid"). This includes reading forces and writing displacements. - Enabled mesh motion solvers that do not register a pointDisplacement field (such as the RBFMeshMotionSolver from solids4foam) to work with the adapter [#241](https://github.com/precice/openfoam-adapter/pull/241) - Added timers for tracking the time spent in the adapter and preCICE (disabled by default) [#256](https://github.com/precice/openfoam-adapter/pull/256). - Added a warning for trying to build without pkg-config being available and more suggestions for possible problems [#220](https://github.com/precice/openfoam-adapter/pull/220). @@ -24,7 +24,7 @@ Read more details in the issue [#52: Releases and versioning](https://github.com - Removed the default `-j 4` option from the wmake command. Instead, documented the `WM_NCOMPPROCS` option of OpenFOAM. [#244](https://github.com/precice/openfoam-adapter/pull/244) - Changed virtual function declarations to explicitly define one (only) of virtual/override/final. If you need to extend a method marked as `final`, please report. [#245](https://github.com/precice/openfoam-adapter/pull/245) - Changed the xy-plane error to a warning, to support 2D axisymmetric cases. [#246](https://github.com/precice/openfoam-adapter/pull/246) -- OpenFOAM version bumped to v2206 in GitHub Actions (including preCICE v2.3.0 --> v2.4.0) and documentation [#230](https://github.com/precice/openfoam-adapter/pull/230). +- OpenFOAM version bumped to v2206 in GitHub Actions (including preCICE v2.3.0 --> v2.5.0) and documentation [#230](https://github.com/precice/openfoam-adapter/pull/230). ### Removed From 65222e0ae3d9f291e58cfc99f9bf6d4a7d8b85d2 Mon Sep 17 00:00:00 2001 From: Gerasimos Chourdakis Date: Mon, 14 Nov 2022 09:49:35 +0100 Subject: [PATCH 31/31] Bump version to v1.2.0 --- Adapter.C | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Adapter.C b/Adapter.C index 697cd51a..98560abd 100644 --- a/Adapter.C +++ b/Adapter.C @@ -10,7 +10,7 @@ preciceAdapter::Adapter::Adapter(const Time& runTime, const fvMesh& mesh) : runTime_(runTime), mesh_(mesh) { - adapterInfo("Loaded the OpenFOAM-preCICE adapter - v1.1.0 + unreleased changes.", "info"); + adapterInfo("Loaded the OpenFOAM-preCICE adapter - v1.2.0.", "info"); return; }