diff --git a/.github/workflows/build-custom.yml b/.github/workflows/build-custom.yml new file mode 100644 index 00000000..d1651454 --- /dev/null +++ b/.github/workflows/build-custom.yml @@ -0,0 +1,214 @@ +name: Custom build (manual) # Unfortunately, we cannot modify the name: https://github.community/t/github-actions-dynamic-name-of-the-workflow-with-workflow-dispatch/150327 +on: + workflow_dispatch: + inputs: + virtualEnvironment: + description: 'Virtual Environment' + default: 'ubuntu-18.04' + required: true + type: choice + options: + - ubuntu-20.04 + - ubuntu-18.04 + refAdapter: + description: 'Ref (branch/tag/commit) of the OpenFOAM adapter to build' + default: 'develop' + required: true + versionOpenFOAM: + description: 'Version of OpenFOAM to build with' + required: true + type: choice + options: + - OpenFOAMv2112 + - OpenFOAMv2106 + - OpenFOAMv2012 + - OpenFOAMv2006 + - OpenFOAMv1912 + - OpenFOAM9 + - OpenFOAM8 + - OpenFOAM7 + - OpenFOAM6 + - OpenFOAM5 + versionpreCICE: + description: 'Version of preCICE to build with' + default: '2.3.0' + required: true + runTutorialHeatedPlate: + description: Run tutorial flow-over-heated-plate + type: boolean + default: true + required: true + runTutorialQuickstart: + description: Run tutorial quickstart + type: boolean + default: true + required: true + runTutorialPartitionedPipe: + description: Run tutorial partitioned-pipe + type: boolean + default: true + required: true + branchTutorials: + description: 'Branch of the tutorials to use' + default: 'master' + required: true + +jobs: + build: + runs-on: ${{ github.event.inputs.virtualEnvironment }} + steps: + - name: Report log + run: | + echo "Initiated by: ${{ github.actor }}" + echo "Runs on: ${{ github.event.inputs.virtualEnvironment }}" + echo "Adapter ref (branch/tag/commit): ${{ github.event.inputs.refAdapter }}" + echo "OpenFOAM version: ${{ github.event.inputs.versionOpenFOAM }}" + echo "preCICE version: ${{ github.event.inputs.versionpreCICE }}" + echo "Run tutorial flow-over-heated-plate: ${{ github.event.inputs.runTutorialHeatedPlate }}" + echo "Run tutorial quickstart: ${{ github.event.inputs.runTutorialQuickstart }}" + echo "Run tutorial partitioned-pipe: ${{ github.event.inputs.runTutorialPartitionedPipe }}" + echo "Tutorials branch: ${{ github.event.inputs.branchTutorials }}" + - name: Check out repository + uses: actions/checkout@v2 + with: + ref: ${{ github.event.inputs.refAdapter }} + - name: Install OpenFOAM (no cache) + id: installOpenFOAM + run: | + case "${{ github.event.inputs.versionOpenFOAM }}" in + OpenFOAMv2112) + wget -q -O - https://dl.openfoam.com/add-debian-repo.sh | sudo bash + sudo apt-get install openfoam2112-dev + echo "::set-output name=openfoam_exec::/usr/bin/openfoam2112";; + OpenFOAMv2106) + wget -q -O - https://dl.openfoam.com/add-debian-repo.sh | sudo bash + sudo apt-get install openfoam2106-dev + echo "::set-output name=openfoam_exec::/usr/bin/openfoam2106";; + OpenFOAMv2012) + wget -q -O - https://dl.openfoam.com/add-debian-repo.sh | sudo bash + sudo apt-get install openfoam2012-dev + echo "::set-output name=openfoam_exec::/usr/bin/openfoam2012";; + OpenFOAMv2006) + wget -q -O - https://dl.openfoam.com/add-debian-repo.sh | sudo bash + sudo apt-get install openfoam2006-dev + echo "::set-output name=openfoam_exec::/usr/bin/openfoam2006";; + OpenFOAMv1912) + 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";; + OpenFOAM9) + 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 openfoam9 + echo "::set-output name=openfoam_exec::. /opt/openfoam9/etc/bashrc &&";; + OpenFOAM8) + 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 openfoam8 + echo "::set-output name=openfoam_exec::. /opt/openfoam8/etc/bashrc &&";; + OpenFOAM7) + 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 openfoam7 + echo "::set-output name=openfoam_exec::. /opt/openfoam7/etc/bashrc &&";; + OpenFOAM6) + echo "OpenFOAM 6 is only available on Ubuntu 18.04 or older." + 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 openfoam6 + echo "::set-output name=openfoam_exec::. /opt/openfoam6/etc/bashrc &&";; + OpenFOAM5) + echo "OpenFOAM 5 is only available on Ubuntu 18.04 or older." + 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 openfoam5 + echo "::set-output name=openfoam_exec::. /opt/openfoam5/etc/bashrc &&";; + *) + echo "I cannot find ${{ github.event.inputs.refAdapter }} in my known options." + exit 1;; + esac + - name: Install preCICE (no cache) + run: | + if [ "${{ github.event.inputs.virtualEnvironment }}" == "ubuntu-20.04" ] + then + wget "https://github.com/precice/precice/releases/download/v${{ github.event.inputs.versionpreCICE }}/libprecice2_${{ github.event.inputs.versionpreCICE }}_focal.deb" + sudo apt install "./libprecice2_${{ github.event.inputs.versionpreCICE }}_focal.deb" + elif [ "${{ github.event.inputs.virtualEnvironment }}" == "ubuntu-18.04" ] + then + wget "https://github.com/precice/precice/releases/download/v${{ github.event.inputs.versionpreCICE }}/libprecice2_${{ github.event.inputs.versionpreCICE }}_bionic.deb" + sudo apt install "./libprecice2_${{ github.event.inputs.versionpreCICE }}_bionic.deb" + fi + - name: Build OpenFOAM-preCICE adapter + run: | + ${{steps.installOpenFOAM.outputs.openfoam_exec}} ./Allwmake + - name: Get tutorials + run: | + git clone https://github.com/precice/tutorials.git --branch ${{ github.event.inputs.branchTutorials }} --depth 1 + - name: Run tutorial flow-over-heated-plate + run: | + if ${{ github.event.inputs.runTutorialHeatedPlate }} + then + cd tutorials/flow-over-heated-plate/fluid-openfoam + ${{steps.installOpenFOAM.outputs.openfoam_exec}} ./run.sh | tee fluid-openfoam.log 2>&1 & + PIDfluid=$! + cd ../solid-openfoam + ${{steps.installOpenFOAM.outputs.openfoam_exec}} ./run.sh | tee solid-openfoam.log 2>&1 + wait $PIDfluid + fi + - name: Run tutorial quickstart + run: | + if ${{ github.event.inputs.runTutorialQuickstart }} + then + cd tutorials/quickstart/fluid-openfoam + if [ "${{ github.event.inputs.versionOpenFOAM }}" == "OpenFOAM5" ] + then + echo "Manually changing from pimpleFoam to pimpleDyMFoam for compatibility with OpenFOAM 5." + sed -i 's/pimpleFoam/pimpleDyMFoam/g' system/controlDict + fi + ${{steps.installOpenFOAM.outputs.openfoam_exec}} ./run.sh | tee fluid-openfoam.log 2>&1 & + PIDfluid=$! + cd ../solid-cpp + cmake . && make && ./run.sh | tee solid-cpp.log 2>&1 + wait $PIDfluid + fi + - name: Run tutorial partitioned-pipe + run: | + if ${{ github.event.inputs.runTutorialPartitionedPipe }} + then + cd tutorials/partitioned-pipe/fluid1-openfoam-pimplefoam + ${{steps.installOpenFOAM.outputs.openfoam_exec}} ./run.sh | tee fluid1-openfoam-pimplefoam.log 2>&1 & + PIDfluid=$! + cd ../fluid2-openfoam-pimplefoam + ${{steps.installOpenFOAM.outputs.openfoam_exec}} ./run.sh | tee fluid2-openfoam-pimplefoam.log 2>&1 & + wait $PIDfluid + fi + - name: Archive logs + uses: actions/upload-artifact@v2 + with: + name: logs + path: | + Allwmake.log + wmake.log + ldd.log + tutorials/flow-over-heated-plate/fluid-openfoam/fluid-openfoam.log + tutorials/flow-over-heated-plate/solid-openfoam/solid-openfoam.log + tutorials/quickstart/fluid-openfoam/fluid-openfoam.log + tutorials/quickstart/solid-cpp/solid-cpp.log + tutorials/partitioned-pipe/fluid1-openfoam-pimplefoam/fluid1-openfoam-pimplefoam.log + tutorials/partitioned-pipe/fluid2-openfoam-pimplefoam/fluid2-openfoam-pimplefoam.log + - name: Archive case files + uses: actions/upload-artifact@v2 + with: + name: case-files + path: | + tutorials/flow-over-heated-plate/fluid-openfoam/* + tutorials/flow-over-heated-plate/solid-openfoam/* + tutorials/quickstart/fluid-openfoam/* + tutorials/quickstart/solid-cpp/* + tutorials/partitioned-pipe/fluid1-openfoam-pimplefoam/* + tutorials/partitioned-pipe/fluid2-openfoam-pimplefoam/* diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d8de24ce..2a7d3981 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,5 +1,23 @@ -name: Build with OpenFOAM v2012 -on: [push, pull_request] +name: Build with OpenFOAM v2112 +on: + push: + branches-ignore: + - 'OpenFOAM*' + paths-ignore: + - 'docs/**' + - 'tools/**' + - 'CHANGELOG.md' + - 'CONTRIBUTING.md' + - 'README.md' + pull_request: + branches-ignore: + - 'OpenFOAM*' + paths-ignore: + - 'docs/**' + - 'tools/**' + - 'CHANGELOG.md' + - 'CONTRIBUTING.md' + - 'README.md' jobs: build: runs-on: ubuntu-20.04 @@ -21,4 +39,4 @@ jobs: snapshot: '/' exclude: '/boot /data /dev /mnt /proc /run /sys' - name: Build OpenFOAM-preCICE adapter - run: /usr/bin/openfoam2012 ./Allwmake + run: /usr/bin/openfoam2112 ./Allwmake diff --git a/.github/workflows/check-format.yml b/.github/workflows/check-format.yml index 7140b81c..1ade288c 100644 --- a/.github/workflows/check-format.yml +++ b/.github/workflows/check-format.yml @@ -7,7 +7,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Run clang-format style check for C/C++ programs. - uses: jidicula/clang-format-action@v3.3.0 + uses: jidicula/clang-format-action@main with: clang-format-version: '11' check-path: '.' diff --git a/.github/workflows/check-links.yml b/.github/workflows/check-links.yml new file mode 100644 index 00000000..f7e0ce61 --- /dev/null +++ b/.github/workflows/check-links.yml @@ -0,0 +1,14 @@ +name: Check links (manual) +on: workflow_dispatch +jobs: + check_links: + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v2 + - name: Check links in markdown files (markdown-link-check) + uses: gaurav-nelson/github-action-markdown-link-check@v1 + with: + use-quiet-mode: 'yes' + use-verbose-mode: 'no' + config-file: '.markdown-link-check-config.json' diff --git a/.github/workflows/check-markdown.yml b/.github/workflows/check-markdown.yml index 5bdd3d09..63a0df9a 100644 --- a/.github/workflows/check-markdown.yml +++ b/.github/workflows/check-markdown.yml @@ -1,4 +1,4 @@ -name: Lint docs and check links +name: Lint docs on: [push, pull_request] jobs: check_md: @@ -12,9 +12,3 @@ jobs: config: .markdownlint.json files: '.' ignore: changelog-entries - - name: Check links in markdown files (markdown-link-check) - uses: gaurav-nelson/github-action-markdown-link-check@v1 - with: - use-quiet-mode: 'yes' - use-verbose-mode: 'no' - config-file: '.markdown-link-check-config.json' diff --git a/.github/workflows/install-dependencies.sh b/.github/workflows/install-dependencies.sh index ffb18ae2..3c2f2363 100755 --- a/.github/workflows/install-dependencies.sh +++ b/.github/workflows/install-dependencies.sh @@ -1,9 +1,9 @@ #!/bin/bash -e -# Install OpenFOAM v2012 +# Install OpenFOAM v2112 wget -q -O - https://dl.openfoam.com/add-debian-repo.sh | sudo bash -sudo apt-get install openfoam2012-dev +sudo apt-get install openfoam2112-dev -# Install preCICE v2.2.0 -wget https://github.com/precice/precice/releases/download/v2.2.0/libprecice2_2.2.0_focal.deb -sudo apt install ./libprecice2_2.2.0_focal.deb \ No newline at end of file +# 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 diff --git a/Adapter.C b/Adapter.C index 790ed74a..1d6ef3e9 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.0.0.", "info"); + adapterInfo("Loaded the OpenFOAM-preCICE adapter - v1.1.0.", "info"); return; } @@ -47,7 +47,7 @@ bool preciceAdapter::Adapter::configFileRead() // Read and display the list of modules DEBUG(adapterInfo(" modules requested : ")); auto modules_ = preciceDict.get("modules"); - for (auto module : modules_) + for (const auto& module : modules_) { DEBUG(adapterInfo(" - " + module + "\n")); @@ -71,7 +71,7 @@ bool preciceAdapter::Adapter::configFileRead() // Every interface is a subdictionary of "interfaces", // each with an arbitrary name. Read all of them and create // a list (here: pointer) of dictionaries. - const auto interfaceDictPtr = preciceDict.findDict("interfaces"); + const auto* interfaceDictPtr = preciceDict.findDict("interfaces"); DEBUG(adapterInfo(" interfaces : ")); // Check if we found any interfaces @@ -87,7 +87,7 @@ bool preciceAdapter::Adapter::configFileRead() { if (interfaceDictEntry.isDict()) { - dictionary interfaceDict = interfaceDictEntry.dict(); + const dictionary& interfaceDict = interfaceDictEntry.dict(); struct InterfaceConfig interfaceConfig; interfaceConfig.meshName = interfaceDict.get("mesh"); @@ -259,22 +259,37 @@ void preciceAdapter::Adapter::configure() { std::string dataName = interfacesConfig_.at(i).writeData.at(j); + unsigned int inModules = 0; + // Add CHT-related coupling data writers - if (CHTenabled_) + if (CHTenabled_ && CHT_->addWriters(dataName, interface)) { - CHT_->addWriters(dataName, interface); + inModules++; } // Add FSI-related coupling data writers - if (FSIenabled_) + if (FSIenabled_ && FSI_->addWriters(dataName, interface)) { - FSI_->addWriters(dataName, interface); + inModules++; } // Add FF-related coupling data writers - if (FFenabled_) + if (FFenabled_ && FF_->addWriters(dataName, interface)) { - FF_->addWriters(dataName, interface); + inModules++; + } + + if (inModules == 0) + { + adapterInfo("I don't know how to write \"" + dataName + + "\". Maybe this is a typo or maybe you need to enable some adapter module?", + "error-deferred"); + } + else if (inModules > 1) + { + adapterInfo("It looks like more than one modules can write \"" + dataName + + "\" and I don't know how to choose. Try disabling one of the modules.", + "error-deferred"); } // NOTE: Add any coupling data writers for your module here. @@ -285,22 +300,28 @@ void preciceAdapter::Adapter::configure() { std::string dataName = interfacesConfig_.at(i).readData.at(j); + unsigned int inModules = 0; + // Add CHT-related coupling data readers - if (CHTenabled_) - { - CHT_->addReaders(dataName, interface); - } + if (CHTenabled_ && CHT_->addReaders(dataName, interface)) inModules++; // Add FSI-related coupling data readers - if (FSIenabled_) - { - FSI_->addReaders(dataName, interface); - } + if (FSIenabled_ && FSI_->addReaders(dataName, interface)) inModules++; // Add FF-related coupling data readers - if (FFenabled_) + if (FFenabled_ && FF_->addReaders(dataName, interface)) inModules++; + + if (inModules == 0) + { + adapterInfo("I don't know how to read \"" + dataName + + "\". Maybe this is a typo or maybe you need to enable some adapter module?", + "error-deferred"); + } + else if (inModules > 1) { - FF_->addReaders(dataName, interface); + adapterInfo("It looks like more than one modules can read \"" + dataName + + "\" and I don't know how to choose. Try disabling one of the modules.", + "error-deferred"); } // NOTE: Add any coupling data readers for your module here. @@ -395,9 +416,6 @@ void preciceAdapter::Adapter::execute() fulfilledReadCheckpoint(); } - // Read the received coupling data from the buffer - readCouplingData(); - // Adjust the timestep, if it is fixed if (!adjustableTimestep_) { @@ -430,6 +448,9 @@ void preciceAdapter::Adapter::execute() } } + // Read the received coupling data from the buffer + readCouplingData(); + // If the coupling is not going to continue, tear down everything // and stop the simulation. if (!isCouplingOngoing()) @@ -447,6 +468,10 @@ void preciceAdapter::Adapter::execute() "The simulation was ended by preCICE. " "Calling the end() methods of any functionObject explicitly.", "info"); + adapterInfo("Great that you are using the OpenFOAM-preCICE adapter! " + "Next to the preCICE library and any other components, please also cite this adapter. " + "Find how on https://precice.org/adapter-openfoam-overview.html.", + "info"); const_cast(runTime_).functionObjects().end(); } @@ -831,411 +856,167 @@ void preciceAdapter::Adapter::setupMeshVolCheckpointing() void preciceAdapter::Adapter::setupCheckpointing() { - // Add fields in the checkpointing list - DEBUG(adapterInfo("Creating a list of checkpointed fields...")); - - /* Find and add all the registered objects in the mesh_ - of type volScalarField - */ - - // Print the available objects of type volScalarField - DEBUG(adapterInfo("Collecting objects of type volScalarField... ")); - - wordList objectNames_ = mesh_.lookupClass().toc(); - - forAll(objectNames_, i) - { - if (mesh_.foundObject(objectNames_[i])) - { - addCheckpointField( - const_cast( - mesh_.lookupObject(objectNames_[i]))); - -#ifdef ADAPTER_DEBUG_MODE - adapterInfo( - "Will be checkpointing " + objectNames_[i]); -#endif - } - else - { - adapterInfo("Could not checkpoint " + objectNames_[i], "warning"); - } - } - - /* Find and add all the registered objects in the mesh_ - of type volVectorField - */ - - // Print the available objects of type volVectorField - DEBUG(adapterInfo("Collecting objects of type volVectorField... ")); - - objectNames_ = mesh_.lookupClass().toc(); - - forAll(objectNames_, i) - { - if (mesh_.foundObject(objectNames_[i])) - { - addCheckpointField( - const_cast( - mesh_.lookupObject(objectNames_[i]))); + // Add fields in the checkpointing list - sorted for parallel consistency + DEBUG(adapterInfo("Adding in checkpointed fields...")); -#ifdef ADAPTER_DEBUG_MODE - adapterInfo( - "Will be checkpointing " + objectNames_[i]); -#endif - } - else - { - adapterInfo("Could not checkpoint " + objectNames_[i], "warning"); - } +#undef doLocalCode +#define doLocalCode(GeomField) \ + /* Checkpoint registered GeomField objects */ \ + for (const word& obj : mesh_.sortedNames()) \ + { \ + addCheckpointField(mesh_.thisDb().getObjectPtr(obj)); \ + DEBUG(adapterInfo("Checkpoint " + obj + " : " #GeomField)); \ } - // Print the available objects of type surfaceScalarField - DEBUG(adapterInfo("Collecting objects of type surfaceScalarField...")); - - /* Find and add all the registered objects in the mesh_ - of type surfaceScalarField - */ - objectNames_ = mesh_.lookupClass().toc(); + doLocalCode(volScalarField); + doLocalCode(volVectorField); + doLocalCode(volTensorField); + doLocalCode(volSymmTensorField); - forAll(objectNames_, i) - { - if (mesh_.foundObject(objectNames_[i])) - { - addCheckpointField( - const_cast( - mesh_.lookupObject(objectNames_[i]))); - -#ifdef ADAPTER_DEBUG_MODE - adapterInfo( - "Will be checkpointing " + objectNames_[i]); -#endif - } - else - { - adapterInfo("Could not checkpoint " + objectNames_[i], "warning"); - } - } - - /* Find and add all the registered objects in the mesh_ - of type surfaceVectorField - */ - - // Print the available objects of type surfaceVectorField - DEBUG(adapterInfo("Collecting objects of type surfaceVectorField...")); - - objectNames_ = mesh_.lookupClass().toc(); - - forAll(objectNames_, i) - { - if (mesh_.foundObject(objectNames_[i])) - { - addCheckpointField( - const_cast( - mesh_.lookupObject(objectNames_[i]))); - -#ifdef ADAPTER_DEBUG_MODE - adapterInfo( - "Will be checkpointing " + objectNames_[i]); -#endif - } - else - { - adapterInfo("Could not checkpoint " + objectNames_[i], "warning"); - } - } - - /* Find and add all the registered objects in the mesh_ - of type pointScalarField - */ - - // Print the available objects of type pointScalarField - DEBUG(adapterInfo("Collecting objects of type pointScalarField...")); - - objectNames_ = mesh_.lookupClass().toc(); - - forAll(objectNames_, i) - { - if (mesh_.foundObject(objectNames_[i])) - { - addCheckpointField( - const_cast( - mesh_.lookupObject(objectNames_[i]))); - -#ifdef ADAPTER_DEBUG_MODE - adapterInfo( - "Will be checkpointing " + objectNames_[i]); -#endif - } - else - { - adapterInfo("Could not checkpoint " + objectNames_[i], "warning"); - } - } - - /* Find and add all the registered objects in the mesh_ - of type pointVectorField - */ - - // Print the available objects of type pointVectorField - DEBUG(adapterInfo("Collecting objects of type pointVectorField...")); - - objectNames_ = mesh_.lookupClass().toc(); - - forAll(objectNames_, i) - { - if (mesh_.foundObject(objectNames_[i])) - { - addCheckpointField( - const_cast( - mesh_.lookupObject(objectNames_[i]))); - -#ifdef ADAPTER_DEBUG_MODE - adapterInfo( - "Will be checkpointing " + objectNames_[i]); -#endif - } - else - { - adapterInfo("Could not checkpoint " + objectNames_[i], "warning"); - } - } + doLocalCode(surfaceScalarField); + doLocalCode(surfaceVectorField); + doLocalCode(surfaceTensorField); - - /* Find and add all the registered objects in the mesh_ - of type volTensorField - */ - - // Print the available objects of type volTensorField - DEBUG(adapterInfo("Collecting objects of type volTensorField...")); - - objectNames_ = mesh_.lookupClass().toc(); - - forAll(objectNames_, i) - { - if (mesh_.foundObject(objectNames_[i])) - { - addCheckpointField( - const_cast( - mesh_.lookupObject(objectNames_[i]))); - -#ifdef ADAPTER_DEBUG_MODE - adapterInfo( - "Will be checkpointing " + objectNames_[i]); -#endif - } - else - { - adapterInfo("Could not checkpoint " + objectNames_[i], "warning"); - } - } - - - /* Find and add all the registered objects in the mesh_ - of type surfaceTensorField - */ - - DEBUG(adapterInfo("Collecting objects of type surfaceTensorField...")); - - objectNames_ = mesh_.lookupClass().toc(); - - forAll(objectNames_, i) - { - if (mesh_.foundObject(objectNames_[i])) - { - addCheckpointField( - const_cast( - mesh_.lookupObject(objectNames_[i]))); - -#ifdef ADAPTER_DEBUG_MODE - adapterInfo( - "Will be checkpointing " + objectNames_[i]); -#endif - } - else - { - adapterInfo("Could not checkpoint " + objectNames_[i], "warning"); - } - } - - /* Find and add all the registered objects in the mesh_ - of type pointTensorField - */ - - DEBUG(adapterInfo("Collecting objects of type pointTensorField...")); - - objectNames_ = mesh_.lookupClass().toc(); - - forAll(objectNames_, i) - { - if (mesh_.foundObject(objectNames_[i])) - { - addCheckpointField( - const_cast( - mesh_.lookupObject(objectNames_[i]))); - -#ifdef ADAPTER_DEBUG_MODE - adapterInfo( - "Will be checkpointing " + objectNames_[i]); -#endif - } - else - { - adapterInfo("Could not checkpoint " + objectNames_[i], "warning"); - } - } + doLocalCode(pointScalarField); + doLocalCode(pointVectorField); + doLocalCode(pointTensorField); // NOTE: Add here other object types to checkpoint, if needed. - /* Find and add all the registered objects in the mesh_ - of type volSymmTensorField - */ - - DEBUG(adapterInfo("Collecting objects of type volSymmTensorField...")); - - objectNames_ = mesh_.lookupClass().toc(); - - forAll(objectNames_, i) - { - if (mesh_.foundObject(objectNames_[i])) - { - addCheckpointField( - const_cast( - mesh_.lookupObject(objectNames_[i]))); - -#ifdef ADAPTER_DEBUG_MODE - adapterInfo( - "Will be checkpointing " + objectNames_[i]); -#endif - } - else - { - adapterInfo("Could not checkpoint " + objectNames_[i], "warning"); - } - } - return; +#undef doLocalCode } // All mesh checkpointed fields + void preciceAdapter::Adapter::addMeshCheckpointField(surfaceScalarField& field) { - surfaceScalarField* copy = new surfaceScalarField(field); - meshSurfaceScalarFields_.push_back(&field); - meshSurfaceScalarFieldCopies_.push_back(copy); - return; + { + meshSurfaceScalarFields_.push_back(&field); + meshSurfaceScalarFieldCopies_.push_back(new surfaceScalarField(field)); + } } void preciceAdapter::Adapter::addMeshCheckpointField(surfaceVectorField& field) { - surfaceVectorField* copy = new surfaceVectorField(field); - meshSurfaceVectorFields_.push_back(&field); - meshSurfaceVectorFieldCopies_.push_back(copy); - return; + { + meshSurfaceVectorFields_.push_back(&field); + meshSurfaceVectorFieldCopies_.push_back(new surfaceVectorField(field)); + } } void preciceAdapter::Adapter::addMeshCheckpointField(volVectorField& field) { - volVectorField* copy = new volVectorField(field); - meshVolVectorFields_.push_back(&field); - meshVolVectorFieldCopies_.push_back(copy); - return; + { + meshVolVectorFields_.push_back(&field); + meshVolVectorFieldCopies_.push_back(new volVectorField(field)); + } } // TODO Internal field for the V0 (volume old) and V00 (volume old-old) fields void preciceAdapter::Adapter::addVolCheckpointField(volScalarField::Internal& field) { - volScalarField::Internal* copy = new volScalarField::Internal(field); - volScalarInternalFields_.push_back(&field); - volScalarInternalFieldCopies_.push_back(copy); - return; + { + volScalarInternalFields_.push_back(&field); + volScalarInternalFieldCopies_.push_back(new volScalarField::Internal(field)); + } } -// All checkpointed fields -void preciceAdapter::Adapter::addCheckpointField(volScalarField& field) + +void preciceAdapter::Adapter::addCheckpointField(volScalarField* field) { - volScalarField* copy = new volScalarField(field); - volScalarFields_.push_back(&field); - volScalarFieldCopies_.push_back(copy); - return; + if (field) + { + volScalarFields_.push_back(field); + volScalarFieldCopies_.push_back(new volScalarField(*field)); + } } -void preciceAdapter::Adapter::addCheckpointField(volVectorField& field) +void preciceAdapter::Adapter::addCheckpointField(volVectorField* field) { - volVectorField* copy = new volVectorField(field); - volVectorFields_.push_back(&field); - volVectorFieldCopies_.push_back(copy); - return; + if (field) + { + volVectorFields_.push_back(field); + volVectorFieldCopies_.push_back(new volVectorField(*field)); + } } -void preciceAdapter::Adapter::addCheckpointField(surfaceScalarField& field) +void preciceAdapter::Adapter::addCheckpointField(surfaceScalarField* field) { - surfaceScalarField* copy = new surfaceScalarField(field); - surfaceScalarFields_.push_back(&field); - surfaceScalarFieldCopies_.push_back(copy); - return; + if (field) + { + surfaceScalarFields_.push_back(field); + surfaceScalarFieldCopies_.push_back(new surfaceScalarField(*field)); + } } -void preciceAdapter::Adapter::addCheckpointField(surfaceVectorField& field) +void preciceAdapter::Adapter::addCheckpointField(surfaceVectorField* field) { - surfaceVectorField* copy = new surfaceVectorField(field); - surfaceVectorFields_.push_back(&field); - surfaceVectorFieldCopies_.push_back(copy); - return; + if (field) + { + surfaceVectorFields_.push_back(field); + surfaceVectorFieldCopies_.push_back(new surfaceVectorField(*field)); + } } -void preciceAdapter::Adapter::addCheckpointField(pointScalarField& field) +void preciceAdapter::Adapter::addCheckpointField(pointScalarField* field) { - pointScalarField* copy = new pointScalarField(field); - pointScalarFields_.push_back(&field); - pointScalarFieldCopies_.push_back(copy); - return; + if (field) + { + pointScalarFields_.push_back(field); + pointScalarFieldCopies_.push_back(new pointScalarField(*field)); + } } -void preciceAdapter::Adapter::addCheckpointField(pointVectorField& field) +void preciceAdapter::Adapter::addCheckpointField(pointVectorField* field) { - pointVectorField* copy = new pointVectorField(field); - pointVectorFields_.push_back(&field); - pointVectorFieldCopies_.push_back(copy); - // TODO: Old time - // pointVectorField * copyOld = new pointVectorField(field.oldTime()); - // pointVectorFieldsOld_.push_back(&(field.oldTime())); - // pointVectorFieldCopiesOld_.push_back(copyOld); - return; + if (field) + { + pointVectorFields_.push_back(field); + pointVectorFieldCopies_.push_back(new pointVectorField(*field)); + // TODO: Old time + // pointVectorFieldsOld_.push_back(const_cast(field->oldTime()))); + // pointVectorFieldCopiesOld_.push_back(new pointVectorField(field->oldTime())); + } } -void preciceAdapter::Adapter::addCheckpointField(volTensorField& field) +void preciceAdapter::Adapter::addCheckpointField(volTensorField* field) { - volTensorField* copy = new volTensorField(field); - volTensorFields_.push_back(&field); - volTensorFieldCopies_.push_back(copy); - return; + if (field) + { + volTensorFields_.push_back(field); + volTensorFieldCopies_.push_back(new volTensorField(*field)); + } } -void preciceAdapter::Adapter::addCheckpointField(surfaceTensorField& field) +void preciceAdapter::Adapter::addCheckpointField(surfaceTensorField* field) { - surfaceTensorField* copy = new surfaceTensorField(field); - surfaceTensorFields_.push_back(&field); - surfaceTensorFieldCopies_.push_back(copy); - return; + if (field) + { + surfaceTensorFields_.push_back(field); + surfaceTensorFieldCopies_.push_back(new surfaceTensorField(*field)); + } } -void preciceAdapter::Adapter::addCheckpointField(pointTensorField& field) +void preciceAdapter::Adapter::addCheckpointField(pointTensorField* field) { - pointTensorField* copy = new pointTensorField(field); - pointTensorFields_.push_back(&field); - pointTensorFieldCopies_.push_back(copy); - return; + if (field) + { + pointTensorFields_.push_back(field); + pointTensorFieldCopies_.push_back(new pointTensorField(*field)); + } } -void preciceAdapter::Adapter::addCheckpointField(volSymmTensorField& field) +void preciceAdapter::Adapter::addCheckpointField(volSymmTensorField* field) { - volSymmTensorField* copy = new volSymmTensorField(field); - volSymmTensorFields_.push_back(&field); - volSymmTensorFieldCopies_.push_back(copy); - return; + if (field) + { + volSymmTensorFields_.push_back(field); + volSymmTensorFieldCopies_.push_back(new volSymmTensorField(*field)); + } } + // NOTE: Add here methods to add other object types to checkpoint, if needed. void preciceAdapter::Adapter::readCheckpoint() diff --git a/Adapter.H b/Adapter.H index ef46ac48..41487151 100644 --- a/Adapter.H +++ b/Adapter.H @@ -315,37 +315,37 @@ private: // Add checkpoint fields, depending on the type //- Add a volScalarField to checkpoint - void addCheckpointField(volScalarField& field); + void addCheckpointField(volScalarField* field); //- Add a volVectorField to checkpoint - void addCheckpointField(volVectorField& field); + void addCheckpointField(volVectorField* field); //- Add a surfaceScalarField to checkpoint - void addCheckpointField(surfaceScalarField& field); + void addCheckpointField(surfaceScalarField* field); //- Add a surfaceVectorField to checkpoint - void addCheckpointField(surfaceVectorField& field); + void addCheckpointField(surfaceVectorField* field); //- Add a pointScalarField to checkpoint - void addCheckpointField(pointScalarField& field); + void addCheckpointField(pointScalarField* field); //- Add a pointVectorField to checkpoint - void addCheckpointField(pointVectorField& field); + void addCheckpointField(pointVectorField* field); // NOTE: Add here methods to add other object types to checkpoint, // if needed. //- Add a volTensorField to checkpoint - void addCheckpointField(volTensorField& field); + void addCheckpointField(volTensorField* field); //- Add a surfaceTensorField to checkpoint - void addCheckpointField(surfaceTensorField& field); + void addCheckpointField(surfaceTensorField* field); //- Add a pointTensorField to checkpoint - void addCheckpointField(pointTensorField& field); + void addCheckpointField(pointTensorField* field); //- Add a volSymmTensorField to checkpoint - void addCheckpointField(volSymmTensorField& field); + void addCheckpointField(volSymmTensorField* field); //- Read the checkpoint - restore the mesh fields and time void readMeshCheckpoint(); diff --git a/Allwmake b/Allwmake index 2736191d..3313220b 100755 --- a/Allwmake +++ b/Allwmake @@ -32,11 +32,24 @@ log "Building the OpenFOAM-preCICE adapter..." # Export the environment variables export ADAPTER_PREP_FLAGS export ADAPTER_TARGET_DIR -ADAPTER_PKG_CONFIG_CFLAGS="$(pkg-config --silence-errors --cflags libprecice)" + +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)" +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="" +fi export ADAPTER_PKG_CONFIG_CFLAGS -ADAPTER_PKG_CONFIG_LIBS="$(pkg-config --silence-errors --libs libprecice)" 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:" @@ -66,11 +79,6 @@ log "" log "The adapter will be built into ${ADAPTER_TARGET_DIR}" log "Additional preprocessor/compiler options: ${ADAPTER_PREP_FLAGS}" -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}" - # Run wmake (build the adapter) and check the exit code log "" log "Building with WMake (see the wmake.log log file)...\n" diff --git a/CHANGELOG.md b/CHANGELOG.md index d0393903..16d551a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,32 @@ Read more details in the issue [#52: Releases and versioning](https://github.com +## [Unreleased] + +## [v1.1.0] 2022-02-08 + +### Added + +- Added a check for data fields and supported location types of the coupling interface [#206](https://github.com/precice/openfoam-adapter/pull/206). +- Extended the adapter's DEBUG output to print the rank in addition to the message in parallel runs +[#201](https://github.com/precice/openfoam-adapter/pull/201). +- Added a custom build GitHub workflow to check building the adapter with any supported OpenFOAM version [#214](https://github.com/precice/openfoam-adapter/pull/214). +- Added a release pull request template and documented the versioning strategy and release artifact names. [#216](https://github.com/precice/openfoam-adapter/pull/216) +- Added a hint to also cite the adapter, at the end of the coupling. [#218](https://github.com/precice/openfoam-adapter/pull/218) + +### Changed + +- Removed explicit casting of boundary conditions in the adapter's write function in order to allow more boundary conditions to be compatible with the adapter (e.g. groovyBC) [#195](https://github.com/precice/openfoam-adapter/pull/195). +- Cleaned-up the handling of adding checkpoint fields and replaced various unnecessary copies by references [#209](https://github.com/precice/openfoam-adapter/pull/209). +- OpenFOAM version bumped to v2112 in GitHub Actions (including preCICE v2.2.1 --> v2.3.0) and documentation. GitHub Action clang-format-action switched to its main branch. [#211](https://github.com/precice/openfoam-adapter/pull/211). +- Disabled automatic checking of links in GitHub Actions. This is now a manual workflow [#215](https://github.com/precice/openfoam-adapter/pull/215). + +### Fixed + +- Fixed a potential memory access issue in the xy-alignment check for parallel 2D cases [#202](https://github.com/precice/openfoam-adapter/issues/202). +- Fixed a bug that was not allowing more than one module at the same time and added an error message for the case when a dataset is not known by any or too many modules. [#197](https://github.com/precice/openfoam-adapter/pull/197). +- Fixed the misplaced data reading in the adapter 'advance' function [#188](https://github.com/precice/openfoam-adapter/pull/188). + ## [v1.0.0] 2021-04-29 ### Added diff --git a/CHT/CHT.C b/CHT/CHT.C index 0c05000d..e51342dd 100644 --- a/CHT/CHT.C +++ b/CHT/CHT.C @@ -46,7 +46,7 @@ bool preciceAdapter::CHT::ConjugateHeatTransfer::configure(const IOdictionary& a bool preciceAdapter::CHT::ConjugateHeatTransfer::readConfig(const IOdictionary& adapterConfig) { - const dictionary CHTdict = adapterConfig.subOrEmptyDict("CHT"); + const dictionary& CHTdict = adapterConfig.subOrEmptyDict("CHT"); // Read the solver type (if not specified, it is determined automatically) solverType_ = CHTdict.lookupOrDefault("solverType", ""); @@ -91,7 +91,7 @@ std::string preciceAdapter::CHT::ConjugateHeatTransfer::determineSolverType() if (mesh_.foundObject("p")) { - volScalarField p_ = mesh_.lookupObject("p"); + const volScalarField& p_ = mesh_.lookupObject("p"); if (p_.dimensions() == pressureDimensionsCompressible) { @@ -118,8 +118,10 @@ std::string preciceAdapter::CHT::ConjugateHeatTransfer::determineSolverType() return solverType; } -void preciceAdapter::CHT::ConjugateHeatTransfer::addWriters(std::string dataName, Interface* interface) +bool preciceAdapter::CHT::ConjugateHeatTransfer::addWriters(std::string dataName, Interface* interface) { + bool found = true; // Set to false later, if needed. + if (dataName.find("Sink-Temperature") == 0) { interface->addCouplingDataWriter( @@ -194,7 +196,7 @@ void preciceAdapter::CHT::ConjugateHeatTransfer::addWriters(std::string dataName } else { - adapterInfo("Unknown data type - cannot add " + dataName + ".", "error"); + found = false; } // NOTE: If you want to couple another variable, you need @@ -202,10 +204,14 @@ void preciceAdapter::CHT::ConjugateHeatTransfer::addWriters(std::string dataName // writer here (and as a reader below). // The argument of the dataName.compare() needs to match // the one provided in the adapter's configuration file. + + return found; } -void preciceAdapter::CHT::ConjugateHeatTransfer::addReaders(std::string dataName, Interface* interface) +bool preciceAdapter::CHT::ConjugateHeatTransfer::addReaders(std::string dataName, Interface* interface) { + bool found = true; // Set to false later, if needed. + if (dataName.find("Sink-Temperature") == 0) { interface->addCouplingDataReader( @@ -280,7 +286,7 @@ void preciceAdapter::CHT::ConjugateHeatTransfer::addReaders(std::string dataName } else { - adapterInfo("Unknown data type - cannot add " + dataName + ".", "error"); + found = false; } // NOTE: If you want to couple another variable, you need @@ -288,4 +294,6 @@ void preciceAdapter::CHT::ConjugateHeatTransfer::addReaders(std::string dataName // reader here (and as a writer above). // The argument of the dataName.compare() needs to match // the one provided in the adapter's configuration file. + + return found; } diff --git a/CHT/CHT.H b/CHT/CHT.H index d4bf03fb..2f0c527f 100644 --- a/CHT/CHT.H +++ b/CHT/CHT.H @@ -60,10 +60,10 @@ public: bool configure(const IOdictionary& adapterConfig); //- Add coupling data writers - void addWriters(std::string dataName, Interface* interface); + bool addWriters(std::string dataName, Interface* interface); //- Add coupling data readers - void addReaders(std::string dataName, Interface* interface); + bool addReaders(std::string dataName, Interface* interface); }; } diff --git a/CHT/HeatFlux.C b/CHT/HeatFlux.C index cdf5fd25..27dcfa41 100644 --- a/CHT/HeatFlux.C +++ b/CHT/HeatFlux.C @@ -28,8 +28,7 @@ void preciceAdapter::CHT::HeatFlux::write(double* buffer, bool meshConnectivity, int patchID = patchIDs_.at(j); const scalarField gradientPatch( - refCast( - T_->boundaryField()[patchID]) + (T_->boundaryField()[patchID]) .snGrad()); // Extract the effective conductivity on the patch @@ -103,6 +102,28 @@ void preciceAdapter::CHT::HeatFlux::read(double* buffer, const unsigned int dim) } } +bool preciceAdapter::CHT::HeatFlux::isLocationTypeSupported(const bool meshConnectivity) const +{ + // For cases with mesh connectivity, we support: + // - face nodes, only for writing + // - face centers, only for reading + // However, since we do not distinguish between reading and writing in the code, we + // always return true and offload the handling to the user. + if (meshConnectivity) + { + return true; + } + else + { + return (this->locationType_ == LocationType::faceCenters); + } +} + +std::string preciceAdapter::CHT::HeatFlux::getDataName() const +{ + return "HeatFlux"; +} + //----- preciceAdapter::CHT::HeatFlux_Compressible ---------------------------- preciceAdapter::CHT::HeatFlux_Compressible::HeatFlux_Compressible( diff --git a/CHT/HeatFlux.H b/CHT/HeatFlux.H index dc000bed..d1e34c0e 100644 --- a/CHT/HeatFlux.H +++ b/CHT/HeatFlux.H @@ -39,6 +39,11 @@ public: // the gradient of the temperature field virtual void read(double* buffer, const unsigned int dim); + bool isLocationTypeSupported(const bool meshConnectivity) const override; + + //- Get the name of the current data field + std::string getDataName() const override; + //- Destructor virtual ~HeatFlux() {}; }; diff --git a/CHT/HeatTransferCoefficient.C b/CHT/HeatTransferCoefficient.C index d084f54c..8da03c09 100644 --- a/CHT/HeatTransferCoefficient.C +++ b/CHT/HeatTransferCoefficient.C @@ -115,6 +115,28 @@ void preciceAdapter::CHT::HeatTransferCoefficient::read(double* buffer, const un } } +bool preciceAdapter::CHT::HeatTransferCoefficient::isLocationTypeSupported(const bool meshConnectivity) const +{ + // For cases with mesh connectivity, we support: + // - face nodes, only for writing + // - face centers, only for reading + // However, since we do not distinguish between reading and writing in the code, we + // always return true and offload the handling to the user. + if (meshConnectivity) + { + return true; + } + else + { + return (this->locationType_ == LocationType::faceCenters); + } +} + +std::string preciceAdapter::CHT::HeatTransferCoefficient::getDataName() const +{ + return "HeatTransferCoefficient"; +} + //----- preciceAdapter::CHT::HeatTransferCoefficient_Compressible ------------- diff --git a/CHT/HeatTransferCoefficient.H b/CHT/HeatTransferCoefficient.H index 76660636..f0caa2de 100644 --- a/CHT/HeatTransferCoefficient.H +++ b/CHT/HeatTransferCoefficient.H @@ -40,6 +40,11 @@ public: //- Read the heat transfer coefficient values from the buffer virtual void read(double* buffer, const unsigned int dim); + bool isLocationTypeSupported(const bool meshConnectivity) const override; + + //- Get the name of the current data field + std::string getDataName() const override; + //- Destructor virtual ~HeatTransferCoefficient() {}; }; diff --git a/CHT/KappaEffective.C b/CHT/KappaEffective.C index 4425ba24..4ec5963a 100644 --- a/CHT/KappaEffective.C +++ b/CHT/KappaEffective.C @@ -62,7 +62,7 @@ preciceAdapter::CHT::KappaEff_Incompressible::KappaEff_Incompressible( DEBUG(adapterInfo(" Name of turbulent thermal diffusivity: " + nameAlphat_)); // Get the preciceDict/CHT dictionary - const dictionary CHTDict = + const dictionary& CHTDict = mesh_.lookupObject("preciceDict").subOrEmptyDict("CHT"); // Read the Prandtl number @@ -119,8 +119,8 @@ void preciceAdapter::CHT::KappaEff_Incompressible::extract(uint patchID, bool me // Does the turbulent thermal diffusivity exist in the object registry? if (mesh_.foundObject(nameAlphat_)) { - const scalarField& alphat( - mesh_.lookupObject(nameAlphat_).boundaryField()[patchID]); + const scalarField& alphat = + mesh_.lookupObject(nameAlphat_).boundaryField()[patchID]; alphaEff = nu / Pr_.value() + alphat; } @@ -172,7 +172,7 @@ preciceAdapter::CHT::KappaEff_Basic::KappaEff_Basic( DEBUG(adapterInfo(" Name of conductivity: " + nameKappa_)); // Get the preciceDict/CHT dictionary - const dictionary CHTDict = + const dictionary& CHTDict = mesh_.lookupObject("preciceDict").subOrEmptyDict("CHT"); // Read the conductivity diff --git a/CHT/SinkTemperature.C b/CHT/SinkTemperature.C index 11746875..8492119c 100644 --- a/CHT/SinkTemperature.C +++ b/CHT/SinkTemperature.C @@ -93,3 +93,25 @@ void preciceAdapter::CHT::SinkTemperature::read(double* buffer, const unsigned i } } } + +bool preciceAdapter::CHT::SinkTemperature::isLocationTypeSupported(const bool meshConnectivity) const +{ + // For cases with mesh connectivity, we support: + // - face nodes, only for writing + // - face centers, only for reading + // However, since we do not distinguish between reading and writing in the code, we + // always return true and offload the handling to the user. + if (meshConnectivity) + { + return true; + } + else + { + return (this->locationType_ == LocationType::faceCenters); + } +} + +std::string preciceAdapter::CHT::SinkTemperature::getDataName() const +{ + return "SinkTemperature"; +} diff --git a/CHT/SinkTemperature.H b/CHT/SinkTemperature.H index 5c92b7c6..8b66896e 100644 --- a/CHT/SinkTemperature.H +++ b/CHT/SinkTemperature.H @@ -30,6 +30,11 @@ public: //- Read the sink temperature values from the buffer void read(double* buffer, const unsigned int dim); + + bool isLocationTypeSupported(const bool meshConnectivity) const override; + + //- Get the name of the current data field + std::string getDataName() const override; }; } diff --git a/CHT/Temperature.C b/CHT/Temperature.C index b3ab956a..3756471c 100644 --- a/CHT/Temperature.C +++ b/CHT/Temperature.C @@ -74,3 +74,25 @@ void preciceAdapter::CHT::Temperature::read(double* buffer, const unsigned int d } } } + +bool preciceAdapter::CHT::Temperature::isLocationTypeSupported(const bool meshConnectivity) const +{ + // For cases with mesh connectivity, we support: + // - face nodes, only for writing + // - face centers, only for reading + // However, since we do not distinguish between reading and writing in the code, we + // always return true and offload the handling to the user. + if (meshConnectivity) + { + return true; + } + else + { + return (this->locationType_ == LocationType::faceCenters); + } +} + +std::string preciceAdapter::CHT::Temperature::getDataName() const +{ + return "Temperature"; +} diff --git a/CHT/Temperature.H b/CHT/Temperature.H index 722ddb01..0ce85a7c 100644 --- a/CHT/Temperature.H +++ b/CHT/Temperature.H @@ -30,6 +30,11 @@ public: //- Read the temperature values from the buffer void read(double* buffer, const unsigned int dim); + + bool isLocationTypeSupported(const bool meshConnectivity) const override; + + //- Get the name of the current data field + std::string getDataName() const override; }; } diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 633f8f3e..ca2cd78a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,3 +13,14 @@ merge conflicts and we will merge these files at the time we release a new versi ## Code formatting You can format all files with clang-format 11 by running `./tools/format-code.sh`. + +## Automatic checks + +We check every contribution with a few GitHub Actions workflows that report at the bottom of each pull request. + +There are also a few additional workflows that can be triggered manually: + +- `Custom build`: builds any branch of the repository with any of the available OpenFOAM versions. +- `Check links`: checks the links in all markdown files to verify if they are still reachable. + +Members of the repository can trigger these workflows in the "Actions" tab. diff --git a/CouplingDataUser.C b/CouplingDataUser.C index 50997740..7e84250d 100644 --- a/CouplingDataUser.C +++ b/CouplingDataUser.C @@ -31,9 +31,27 @@ void preciceAdapter::CouplingDataUser::setPatchIDs(std::vector patchIDs) patchIDs_ = patchIDs; } -void preciceAdapter::CouplingDataUser::setLocationsType(std::string locationsType) +void preciceAdapter::CouplingDataUser::setLocationsType(LocationType locationsType) { - locationsType_ = locationsType; + locationType_ = locationsType; +} + +void preciceAdapter::CouplingDataUser::checkDataLocation(const bool meshConnectivity) const +{ + if (this->isLocationTypeSupported(meshConnectivity) == false) + { + std::string location("none"); + if (locationType_ == LocationType::faceCenters) + location = "faceCenters"; + else if (locationType_ == LocationType::faceNodes) + location = "faceNodes"; + + adapterInfo("\"locations = " + location + "\" is not supported for the data \"" + + getDataName() + "\". Please select a different " + "location type, a different data set or provide " + "additional connectivity information.", + "error"); + } } // Dummy implementation which can be overwritten in derived classes if required diff --git a/CouplingDataUser.H b/CouplingDataUser.H index 030635b1..3c994790 100644 --- a/CouplingDataUser.H +++ b/CouplingDataUser.H @@ -1,11 +1,20 @@ #ifndef COUPLINGDATAUSER_H #define COUPLINGDATAUSER_H +#include "Utilities.H" #include #include namespace preciceAdapter { +// A small enum to deal with the different locations of the +// coupling interface +enum class LocationType +{ + none, + faceCenters, + faceNodes +}; class CouplingDataUser { @@ -27,7 +36,7 @@ protected: int dataID_; //- location type of the interface - std::string locationsType_; + LocationType locationType_ = LocationType::none; public: //- Constructor @@ -49,7 +58,10 @@ public: void setPatchIDs(std::vector patchIDs); //- Set the locations type of the interface - void setLocationsType(std::string locationsType); + void setLocationsType(LocationType locationsType); + + // Check if the dataset supports this interface nodes location + void checkDataLocation(const bool meshConnectivity) const; //- option to initialize data in derived data classes virtual void initialize(); @@ -60,6 +72,13 @@ public: //- Read the coupling data from the buffer virtual void read(double* dataBuffer, const unsigned int dim) = 0; + //- Given the meshConnectivity, return if the underlying loactionType of the + //- interface nodes is supported by the data set + virtual bool isLocationTypeSupported(const bool meshConnectivity) const = 0; + + //- Get the name of the current data field + virtual std::string getDataName() const = 0; + //- Destructor virtual ~CouplingDataUser() {} }; diff --git a/FF/FF.C b/FF/FF.C index 5d016e61..6bf0476b 100644 --- a/FF/FF.C +++ b/FF/FF.C @@ -45,7 +45,7 @@ bool preciceAdapter::FF::FluidFluid::configure(const IOdictionary& adapterConfig bool preciceAdapter::FF::FluidFluid::readConfig(const IOdictionary& adapterConfig) { - const dictionary FFdict = adapterConfig.subOrEmptyDict("FF"); + const dictionary& FFdict = adapterConfig.subOrEmptyDict("FF"); // Read the solver type (if not specified, it is determined automatically) solverType_ = FFdict.lookupOrDefault("solverType", ""); @@ -74,7 +74,7 @@ std::string preciceAdapter::FF::FluidFluid::determineSolverType() if (mesh_.foundObject("p")) { - volScalarField p_ = mesh_.lookupObject("p"); + const volScalarField& p_ = mesh_.lookupObject("p"); if (p_.dimensions() == pressureDimensionsCompressible) solverType = "compressible"; @@ -97,8 +97,10 @@ std::string preciceAdapter::FF::FluidFluid::determineSolverType() return solverType; } -void preciceAdapter::FF::FluidFluid::addWriters(std::string dataName, Interface* interface) +bool preciceAdapter::FF::FluidFluid::addWriters(std::string dataName, Interface* interface) { + bool found = true; // Set to false later, if needed. + if (dataName.find("VelocityGradient") == 0) { interface->addCouplingDataWriter( @@ -129,7 +131,7 @@ void preciceAdapter::FF::FluidFluid::addWriters(std::string dataName, Interface* } else { - adapterInfo("Unknown data type - cannot add " + dataName + ".", "error"); + found = false; } // NOTE: If you want to couple another variable, you need @@ -137,10 +139,14 @@ void preciceAdapter::FF::FluidFluid::addWriters(std::string dataName, Interface* // writer here (and as a reader below). // The argument of the dataName.compare() needs to match // the one provided in the adapter's configuration file. + + return found; } -void preciceAdapter::FF::FluidFluid::addReaders(std::string dataName, Interface* interface) +bool preciceAdapter::FF::FluidFluid::addReaders(std::string dataName, Interface* interface) { + bool found = true; // Set to false later, if needed. + if (dataName.find("VelocityGradient") == 0) { interface->addCouplingDataReader( @@ -171,7 +177,7 @@ void preciceAdapter::FF::FluidFluid::addReaders(std::string dataName, Interface* } else { - adapterInfo("Unknown data type - cannot add " + dataName + ".", "error"); + found = false; } // NOTE: If you want to couple another variable, you need @@ -179,4 +185,6 @@ void preciceAdapter::FF::FluidFluid::addReaders(std::string dataName, Interface* // reader here (and as a writer above). // The argument of the dataName.compare() needs to match // the one provided in the adapter's configuration file. + + return found; } diff --git a/FF/FF.H b/FF/FF.H index a8c65582..ded126e0 100644 --- a/FF/FF.H +++ b/FF/FF.H @@ -47,10 +47,10 @@ public: bool configure(const IOdictionary& adapterConfig); //- Add coupling data writers - void addWriters(std::string dataName, Interface* interface); + bool addWriters(std::string dataName, Interface* interface); //- Add coupling data readers - void addReaders(std::string dataName, Interface* interface); + bool addReaders(std::string dataName, Interface* interface); }; } diff --git a/FF/Pressure.C b/FF/Pressure.C index cf2ec770..2d8566e5 100644 --- a/FF/Pressure.C +++ b/FF/Pressure.C @@ -49,3 +49,13 @@ void preciceAdapter::FF::Pressure::read(double* buffer, const unsigned int dim) } } } + +bool preciceAdapter::FF::Pressure::isLocationTypeSupported(const bool meshConnectivity) const +{ + return (this->locationType_ == LocationType::faceCenters); +} + +std::string preciceAdapter::FF::Pressure::getDataName() const +{ + return "Pressure"; +} diff --git a/FF/Pressure.H b/FF/Pressure.H index 6d9efd4f..5506de53 100644 --- a/FF/Pressure.H +++ b/FF/Pressure.H @@ -29,6 +29,11 @@ public: //- Read the pressure values from the buffer void read(double* buffer, const unsigned int dim); + + bool isLocationTypeSupported(const bool meshConnectivity) const override; + + //- Get the name of the current data field + std::string getDataName() const override; }; } diff --git a/FF/PressureGradient.C b/FF/PressureGradient.C index 9d46c1a7..ef8dd9ff 100644 --- a/FF/PressureGradient.C +++ b/FF/PressureGradient.C @@ -22,10 +22,8 @@ void preciceAdapter::FF::PressureGradient::write(double* buffer, bool meshConnec int patchID = patchIDs_.at(j); // Get the pressure gradient boundary patch - scalarField gradientPatch = - refCast( - p_->boundaryFieldRef()[patchID]) - .snGrad(); + const scalarField gradientPatch((p_->boundaryFieldRef()[patchID]) + .snGrad()); // For every cell of the patch forAll(gradientPatch, i) @@ -61,3 +59,13 @@ void preciceAdapter::FF::PressureGradient::read(double* buffer, const unsigned i } } } + +bool preciceAdapter::FF::PressureGradient::isLocationTypeSupported(const bool meshConnectivity) const +{ + return (this->locationType_ == LocationType::faceCenters); +} + +std::string preciceAdapter::FF::PressureGradient::getDataName() const +{ + return "PressureGradient"; +} diff --git a/FF/PressureGradient.H b/FF/PressureGradient.H index 05c5a9f9..47920b7f 100644 --- a/FF/PressureGradient.H +++ b/FF/PressureGradient.H @@ -29,6 +29,11 @@ public: //- Read the pressure gradient values from the buffer void read(double* buffer, const unsigned int dim); + + bool isLocationTypeSupported(const bool meshConnectivity) const override; + + //- Get the name of the current data field + std::string getDataName() const override; }; } diff --git a/FF/Velocity.C b/FF/Velocity.C index 5ff72395..747def6f 100644 --- a/FF/Velocity.C +++ b/FF/Velocity.C @@ -73,3 +73,13 @@ void preciceAdapter::FF::Velocity::read(double* buffer, const unsigned int dim) } } } + +bool preciceAdapter::FF::Velocity::isLocationTypeSupported(const bool meshConnectivity) const +{ + return (this->locationType_ == LocationType::faceCenters); +} + +std::string preciceAdapter::FF::Velocity::getDataName() const +{ + return "Velocity"; +} diff --git a/FF/Velocity.H b/FF/Velocity.H index 3d78460b..17c0dc19 100644 --- a/FF/Velocity.H +++ b/FF/Velocity.H @@ -29,6 +29,11 @@ public: //- Read the velocity values from the buffer void read(double* buffer, const unsigned int dim); + + bool isLocationTypeSupported(const bool meshConnectivity) const override; + + //- Get the name of the current data field + std::string getDataName() const override; }; } diff --git a/FF/VelocityGradient.C b/FF/VelocityGradient.C index f9b7b3cc..8c100602 100644 --- a/FF/VelocityGradient.C +++ b/FF/VelocityGradient.C @@ -22,10 +22,8 @@ void preciceAdapter::FF::VelocityGradient::write(double* buffer, bool meshConnec int patchID = patchIDs_.at(j); // Get the velocity gradient boundary patch - vectorField gradientPatch = - refCast( - U_->boundaryFieldRef()[patchID]) - .snGrad(); + vectorField gradientPatch((U_->boundaryFieldRef()[patchID]) + .snGrad()); // For every cell of the patch forAll(gradientPatch, i) @@ -83,3 +81,13 @@ void preciceAdapter::FF::VelocityGradient::read(double* buffer, const unsigned i } } } + +bool preciceAdapter::FF::VelocityGradient::isLocationTypeSupported(const bool meshConnectivity) const +{ + return (this->locationType_ == LocationType::faceCenters); +} + +std::string preciceAdapter::FF::VelocityGradient::getDataName() const +{ + return "VelocityGradient"; +} diff --git a/FF/VelocityGradient.H b/FF/VelocityGradient.H index 1f3e9a84..c3ce7368 100644 --- a/FF/VelocityGradient.H +++ b/FF/VelocityGradient.H @@ -25,10 +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); + void write(double* buffer, bool meshConnectivity, const unsigned int dim) override; //- Read the velocity gradient values from the buffer - void read(double* buffer, const unsigned int dim); + void read(double* buffer, const unsigned int dim) override; + + bool isLocationTypeSupported(const bool meshConnectivity) const override; + + //- Get the name of the current data field + std::string getDataName() const override; }; } diff --git a/FSI/Displacement.C b/FSI/Displacement.C index 543e26c7..90a6e2de 100644 --- a/FSI/Displacement.C +++ b/FSI/Displacement.C @@ -23,7 +23,7 @@ void preciceAdapter::FSI::Displacement::initialize() { // Initialize appropriate objects for each interface patch, namely the volField and the interpolation object // this is only necessary for face based FSI - if (this->locationsType_ == "faceCenters" || this->locationsType_ == "faceCentres") + if (this->locationType_ == LocationType::faceCenters) { for (unsigned int j = 0; j < patchIDs_.size(); ++j) { @@ -55,7 +55,7 @@ void preciceAdapter::FSI::Displacement::read(double* buffer, const unsigned int // Get the ID of the current patch const unsigned int patchID = patchIDs_.at(j); - if (this->locationsType_ == "faceCenters" || this->locationsType_ == "faceCentres") + if (this->locationType_ == LocationType::faceCenters) { // the boundaryCellDisplacement is a vector and ordered according to the iterator j @@ -75,7 +75,7 @@ void preciceAdapter::FSI::Displacement::read(double* buffer, const unsigned int // Afterwards, continue as usual pointDisplacementFluidPatch = interpolationObjects_[j]->faceToPointInterpolate(cellDisplacement_->boundaryField()[patchID]); } - else if (this->locationsType_ == "faceNodes") + else if (this->locationType_ == LocationType::faceNodes) { // Get the displacement on the patch @@ -92,3 +92,13 @@ void preciceAdapter::FSI::Displacement::read(double* buffer, const unsigned int } } } + +bool preciceAdapter::FSI::Displacement::isLocationTypeSupported(const bool meshConnectivity) const +{ + return (this->locationType_ == LocationType::faceCenters || this->locationType_ == LocationType::faceNodes); +} + +std::string preciceAdapter::FSI::Displacement::getDataName() const +{ + return "Displacement"; +} diff --git a/FSI/Displacement.H b/FSI/Displacement.H index a6ce22c3..64631852 100644 --- a/FSI/Displacement.H +++ b/FSI/Displacement.H @@ -36,10 +36,15 @@ public: const std::string nameCellDisplacement); //- Write the displacement values into the buffer - void write(double* buffer, bool meshConnectivity, const unsigned int dim); + void write(double* buffer, bool meshConnectivity, const unsigned int dim) override; //- Read the displacement values from the buffer - void read(double* buffer, const unsigned int dim); + void read(double* buffer, const unsigned int dim) override; + + bool isLocationTypeSupported(const bool meshConnectivity) const override; + + //- Get the name of the current data field + std::string getDataName() const override; //- We need to initialize the cell-based vector and the interpolation object // in case we want to use the faceCenter location for the coupling diff --git a/FSI/DisplacementDelta.C b/FSI/DisplacementDelta.C index 2629a6d9..ca4e4c2a 100644 --- a/FSI/DisplacementDelta.C +++ b/FSI/DisplacementDelta.C @@ -23,7 +23,7 @@ void preciceAdapter::FSI::DisplacementDelta::initialize() { // Initialize appropriate objects for each interface patch, namely the volField and the interpolation object // this is only necessary for face based FSI - if (this->locationsType_ == "faceCenters" || this->locationsType_ == "faceCentres") + if (this->locationType_ == LocationType::faceCenters) { for (unsigned int j = 0; j < patchIDs_.size(); ++j) { @@ -54,7 +54,7 @@ void preciceAdapter::FSI::DisplacementDelta::read(double* buffer, const unsigned // Get the ID of the current patch const unsigned int patchID = patchIDs_.at(j); - if (this->locationsType_ == "faceCenters" || this->locationsType_ == "faceCentres") + if (this->locationType_ == LocationType::faceCenters) { // the boundaryCellDisplacement is a vector and ordered according to the iterator j @@ -76,7 +76,7 @@ void preciceAdapter::FSI::DisplacementDelta::read(double* buffer, const unsigned // Afterwards, continue as usual pointDisplacementFluidPatch += interpolationObjects_[j]->faceToPointInterpolate(cellDisplacement_->boundaryField()[patchID]); } - else if (this->locationsType_ == "faceNodes") + else if (this->locationType_ == LocationType::faceNodes) { // Get the displacement on the patch @@ -93,3 +93,13 @@ void preciceAdapter::FSI::DisplacementDelta::read(double* buffer, const unsigned } } } + +bool preciceAdapter::FSI::DisplacementDelta::isLocationTypeSupported(const bool meshConnectivity) const +{ + return (this->locationType_ == LocationType::faceCenters || this->locationType_ == LocationType::faceNodes); +} + +std::string preciceAdapter::FSI::DisplacementDelta::getDataName() const +{ + return "DisplacementDelta"; +} diff --git a/FSI/DisplacementDelta.H b/FSI/DisplacementDelta.H index 24317de6..25f162c5 100644 --- a/FSI/DisplacementDelta.H +++ b/FSI/DisplacementDelta.H @@ -36,10 +36,15 @@ public: const std::string nameCellDisplacement); //- Write the displacementDelta values into the buffer - void write(double* buffer, bool meshConnectivity, const unsigned int dim); + void write(double* buffer, bool meshConnectivity, const unsigned int dim) override; //- Read the displacementDelta values from the buffer - void read(double* buffer, const unsigned int dim); + void read(double* buffer, const unsigned int dim) override; + + bool isLocationTypeSupported(const bool meshConnectivity) const override; + + //- Get the name of the current data field + virtual 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 diff --git a/FSI/FSI.C b/FSI/FSI.C index 46d37915..a10e0326 100644 --- a/FSI/FSI.C +++ b/FSI/FSI.C @@ -47,7 +47,7 @@ bool preciceAdapter::FSI::FluidStructureInteraction::configure(const IOdictionar bool preciceAdapter::FSI::FluidStructureInteraction::readConfig(const IOdictionary& adapterConfig) { - const dictionary FSIdict = adapterConfig.subOrEmptyDict("FSI"); + const dictionary& FSIdict = adapterConfig.subOrEmptyDict("FSI"); // Read the solver type (if not specified, it is determined automatically) solverType_ = FSIdict.lookupOrDefault("solverType", ""); @@ -81,7 +81,7 @@ std::string preciceAdapter::FSI::FluidStructureInteraction::determineSolverType( if (mesh_.foundObject("p")) { - volScalarField p_ = mesh_.lookupObject("p"); + const volScalarField& p_ = mesh_.lookupObject("p"); if (p_.dimensions() == pressureDimensionsCompressible) { @@ -109,8 +109,10 @@ std::string preciceAdapter::FSI::FluidStructureInteraction::determineSolverType( } -void preciceAdapter::FSI::FluidStructureInteraction::addWriters(std::string dataName, Interface* interface) +bool preciceAdapter::FSI::FluidStructureInteraction::addWriters(std::string dataName, Interface* interface) { + bool found = true; // Set to false later, if needed. + if (dataName.find("Force") == 0) { interface->addCouplingDataWriter( @@ -141,16 +143,24 @@ void preciceAdapter::FSI::FluidStructureInteraction::addWriters(std::string data ); DEBUG(adapterInfo("Added writer: Stress.")); } + else + { + found = false; + } // NOTE: If you want to couple another variable, you need // to add your new coupling data user as a coupling data // writer here (and as a reader below). // The argument of the dataName.compare() needs to match // the one provided in the adapter's configuration file. + + return found; } -void preciceAdapter::FSI::FluidStructureInteraction::addReaders(std::string dataName, Interface* interface) +bool preciceAdapter::FSI::FluidStructureInteraction::addReaders(std::string dataName, Interface* interface) { + bool found = true; // Set to false later, if needed. + if (dataName.find("Force") == 0) { interface->addCouplingDataReader( @@ -181,10 +191,16 @@ void preciceAdapter::FSI::FluidStructureInteraction::addReaders(std::string data ); DEBUG(adapterInfo("Added reader: Stress.")); } + else + { + found = false; + } // NOTE: If you want to couple another variable, you need // to add your new coupling data user as a coupling data // writer here (and as a writer above). // The argument of the dataName.compare() needs to match // the one provided in the adapter's configuration file. + + return found; } diff --git a/FSI/FSI.H b/FSI/FSI.H index 237a0a9a..3e93d77e 100644 --- a/FSI/FSI.H +++ b/FSI/FSI.H @@ -56,10 +56,10 @@ public: bool configure(const IOdictionary& adapterConfig); //- Add coupling data writers - void addWriters(std::string dataName, Interface* interface); + bool addWriters(std::string dataName, Interface* interface); //- Add coupling data readers - void addReaders(std::string dataName, Interface* interface); + bool addReaders(std::string dataName, Interface* interface); }; } diff --git a/FSI/Force.C b/FSI/Force.C index 480ba9f1..46c298fb 100644 --- a/FSI/Force.C +++ b/FSI/Force.C @@ -31,7 +31,17 @@ void preciceAdapter::FSI::Force::read(double* buffer, const unsigned int dim) this->readFromBuffer(buffer); } -vectorField preciceAdapter::FSI::Force::getFaceVectors(const unsigned int patchID) const +bool preciceAdapter::FSI::Force::isLocationTypeSupported(const bool meshConnectivity) const +{ + return (this->locationType_ == LocationType::faceCenters); +} + +std::string preciceAdapter::FSI::Force::getDataName() const +{ + return "Force"; +} + +Foam::tmp preciceAdapter::FSI::Force::getFaceVectors(const unsigned int patchID) const { // Normal vectors multiplied by face area return mesh_.boundary()[patchID].Sf(); diff --git a/FSI/Force.H b/FSI/Force.H index d18f75a1..062e42c0 100644 --- a/FSI/Force.H +++ b/FSI/Force.H @@ -22,13 +22,18 @@ public: const std::string solverType); //- Write the forces values into the buffer - void write(double* buffer, bool meshConnectivity, const unsigned int dim); + void write(double* buffer, bool meshConnectivity, const unsigned int dim) override; //- Read the forces values from the buffer - void read(double* buffer, const unsigned int dim); + void read(double* buffer, const unsigned int dim) override; + + bool isLocationTypeSupported(const bool meshConnectivity) const override; + + //- Get the name of the current data field + std::string getDataName() const override; //- Returns the normal vectors multiplied by the face area - Foam::vectorField getFaceVectors(const unsigned int patchID) const override; + Foam::tmp getFaceVectors(const unsigned int patchID) const override; //- Destructor ~Force(); diff --git a/FSI/ForceBase.C b/FSI/ForceBase.C index 2ef28e6d..37e1c9e8 100644 --- a/FSI/ForceBase.C +++ b/FSI/ForceBase.C @@ -145,15 +145,13 @@ void preciceAdapter::FSI::ForceBase::writeToBuffer(double* buffer, trho().boundaryField(); // Pressure boundary field - tmp tp = mesh_.lookupObject("p"); - const volScalarField::Boundary& pb( - tp().boundaryField()); + const auto& pb = mesh_.lookupObject("p").boundaryField(); // For every boundary patch of the interface for (const label patchID : patchIDs_) { - - const auto& surface = getFaceVectors(patchID); + tmp tsurface = getFaceVectors(patchID); + const auto& surface = tsurface(); // Pressure forces // FIXME: We need to substract the reference pressure for incompressible calculations diff --git a/FSI/ForceBase.H b/FSI/ForceBase.H index a30c3bb4..38643333 100644 --- a/FSI/ForceBase.H +++ b/FSI/ForceBase.H @@ -45,7 +45,7 @@ public: void readFromBuffer(double* buffer) const; - virtual Foam::vectorField getFaceVectors(const unsigned int patchID) const = 0; + virtual Foam::tmp getFaceVectors(const unsigned int patchID) const = 0; }; } } diff --git a/FSI/Stress.C b/FSI/Stress.C index cec69afe..c5ba6d10 100644 --- a/FSI/Stress.C +++ b/FSI/Stress.C @@ -31,7 +31,17 @@ void preciceAdapter::FSI::Stress::read(double* buffer, const unsigned int dim) this->readFromBuffer(buffer); } -vectorField preciceAdapter::FSI::Stress::getFaceVectors(const unsigned int patchID) const +bool preciceAdapter::FSI::Stress::isLocationTypeSupported(const bool meshConnectivity) const +{ + return (this->locationType_ == LocationType::faceCenters); +} + +std::string preciceAdapter::FSI::Stress::getDataName() const +{ + return "Stress"; +} + +Foam::tmp preciceAdapter::FSI::Stress::getFaceVectors(const unsigned int patchID) const { // face normal vectors return mesh_.boundary()[patchID].nf(); diff --git a/FSI/Stress.H b/FSI/Stress.H index 1f93e2af..0e82aa34 100644 --- a/FSI/Stress.H +++ b/FSI/Stress.H @@ -27,13 +27,18 @@ public: const std::string solverType); //- Write the stress values into the buffer - void write(double* buffer, bool meshConnectivity, const unsigned int dim); + void write(double* buffer, bool meshConnectivity, const unsigned int dim) override; //- Read the stress values from the buffer - void read(double* buffer, const unsigned int dim); + void read(double* buffer, const unsigned int dim) override; + + bool isLocationTypeSupported(const bool meshConnectivity) const override; + + //- Get the name of the current data field + std::string getDataName() const override; //- Returns the face normal vectors (no multiplication by area) - Foam::vectorField getFaceVectors(const unsigned int patchID) const override; + Foam::tmp getFaceVectors(const unsigned int patchID) const override; //- Destructor ~Stress(); diff --git a/Interface.C b/Interface.C index 7268a23b..c90ab5bc 100644 --- a/Interface.C +++ b/Interface.C @@ -14,7 +14,6 @@ preciceAdapter::Interface::Interface( bool meshConnectivity) : precice_(precice), meshName_(meshName), - locationsType_(locationsType), patchNames_(patchNames), meshConnectivity_(meshConnectivity) { @@ -31,6 +30,23 @@ preciceAdapter::Interface::Interface( "warning")); } + if (locationsType == "faceCenters" || locationsType == "faceCentres") + { + locationType_ = LocationType::faceCenters; + } + else if (locationsType == "faceNodes") + { + locationType_ = LocationType::faceNodes; + } + else + { + adapterInfo("Interface points location type \"" + "locations = " + + locationsType + "\" is invalid.", + "error-deferred"); + } + + // For every patch that participates in the coupling for (uint j = 0; j < patchNames.size(); j++) { @@ -62,7 +78,7 @@ void preciceAdapter::Interface::configureMesh(const fvMesh& mesh) // TODO: Reduce code duplication. In the meantime, take care to update // all the branches. - if (locationsType_ == "faceCenters" || locationsType_ == "faceCentres") + if (locationType_ == LocationType::faceCenters) { // Count the data locations for all the patches for (uint j = 0; j < patchIDs_.size(); j++) @@ -102,16 +118,20 @@ void preciceAdapter::Interface::configureMesh(const fvMesh& mesh) { const pointField faceNodes = mesh.boundaryMesh()[patchIDs_.at(j)].localPoints(); + const auto faceNodesSize = faceNodes.size(); //Allocate memory for z-coordinates std::array z_location({0, 0}); constexpr unsigned int z_axis = 2; // Find out about the existing planes // Store z-coordinate of the first layer - z_location[0] = faceNodes[0][z_axis]; + if (faceNodesSize > 0) + { + z_location[0] = faceNodes[0][z_axis]; + } // Go through the remaining points until we find the second z-coordinate // and store it (there are only two allowed in case we are in the xy-layer) - for (int i = 0; i < faceNodes.size(); i++) + for (int i = 0; i < faceNodesSize; i++) { if (z_location[0] == faceNodes[i][z_axis]) { @@ -125,7 +145,7 @@ void preciceAdapter::Interface::configureMesh(const fvMesh& mesh) } // Check if the z-coordinates of all nodes match the z-coordinates we have collected above - for (int i = 0; i < faceNodes.size(); i++) + for (int i = 0; i < faceNodesSize; i++) { if (z_location[0] == faceNodes[i][z_axis] || z_location[1] == faceNodes[i][z_axis]) { @@ -146,7 +166,7 @@ void preciceAdapter::Interface::configureMesh(const fvMesh& mesh) // Pass the mesh vertices information to preCICE precice_.setMeshVertices(meshID_, numDataLocations_, vertices, vertexIDs_); } - else if (locationsType_ == "faceNodes") + else if (locationType_ == LocationType::faceNodes) { // Count the data locations for all the patches for (uint j = 0; j < patchIDs_.size(); j++) @@ -255,14 +275,6 @@ void preciceAdapter::Interface::configureMesh(const fvMesh& mesh) } } } - if (!(locationsType_ == "faceNodes" || locationsType_ == "faceCenters" || locationsType_ == "faceCentres")) - { - FatalErrorInFunction - << "ERROR: interface points location type " - << locationsType_ - << " is invalid." - << exit(FatalError); - } } @@ -277,7 +289,10 @@ void preciceAdapter::Interface::addCouplingDataWriter( couplingDataWriter->setPatchIDs(patchIDs_); // Set the location type in the CouplingDataUser class - couplingDataWriter->setLocationsType(locationsType_); + couplingDataWriter->setLocationsType(locationType_); + + // Set the location type in the CouplingDataUser class + couplingDataWriter->checkDataLocation(meshConnectivity_); // Initilaize class specific data couplingDataWriter->initialize(); @@ -298,7 +313,10 @@ void preciceAdapter::Interface::addCouplingDataReader( couplingDataReader->setPatchIDs(patchIDs_); // Set the location type in the CouplingDataUser class - couplingDataReader->setLocationsType(locationsType_); + couplingDataReader->setLocationsType(locationType_); + + // Check, if the current location type is supported by the data type + couplingDataReader->checkDataLocation(meshConnectivity_); // Initilaize class specific data couplingDataReader->initialize(); diff --git a/Interface.H b/Interface.H index c2713751..bc18134a 100644 --- a/Interface.H +++ b/Interface.H @@ -21,7 +21,7 @@ protected: std::string meshName_; //- Point locations type (faceCenters vs faceNodes) - std::string locationsType_; + LocationType locationType_ {LocationType::none}; //- Mesh ID assigned by preCICE to the interface int meshID_; diff --git a/README.md b/README.md index 7bb82d4e..6602e0ef 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # OpenFOAM-preCICE adapter -[![Build with OpenFOAM v2012](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 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) [![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/Utilities.C b/Utilities.C index 9141a183..2ed0af54 100644 --- a/Utilities.C +++ b/Utilities.C @@ -58,7 +58,7 @@ void adapterInfo(const std::string message, const std::string level) } else if (level.compare("debug") == 0) { - Info << INFO_STR_ADAPTER + Pout << INFO_STR_ADAPTER << "[DEBUG] " << message.c_str() << nl; diff --git a/docs/README.md b/docs/README.md index 92c60076..36027891 100644 --- a/docs/README.md +++ b/docs/README.md @@ -58,4 +58,6 @@ For CHT-specific topics, you may want to additionally look into [2] and for FSI [3] Derek Risseeuw. [Fluid Structure Interaction Modelling of Flapping Wings](https://repository.tudelft.nl/islandora/object/uuid:70beddde-e870-4c62-9a2f-8758b4e49123). Master's thesis, Faculty of Aerospace Engineering, Delft University of Technology, 2019. -{% include disclaimer.html content="This offering is not approved or endorsed by OpenCFD Limited, producer and distributor of the OpenFOAM software via www.openfoam.com, and owner of the OPENFOAM® and OpenCFD® trade marks." %} +{% disclaimer %} +This offering is not approved or endorsed by OpenCFD Limited, producer and distributor of the OpenFOAM software via www.openfoam.com, and owner of the OPENFOAM® and OpenCFD® trade marks. +{% enddisclaimer %} diff --git a/docs/config.md b/docs/config.md index fdb8a001..6371bac7 100644 --- a/docs/config.md +++ b/docs/config.md @@ -122,7 +122,9 @@ 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. -{% include warning.html content="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." %} +{% 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. +{% endwarning %} ## Configuration of the OpenFOAM case @@ -274,8 +276,9 @@ As described already, the data is not stored on the face nodes, but on the face Data is obtained at the face centers, then interpolated to face nodes. Here, we have provided mesh connectivity and finally, preCICE performs the nearest-projection mapping. 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). -{% include note.html content="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. -" %} +{% 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. +{% endnote %} ### Additional properties for some solvers diff --git a/docs/get.md b/docs/get.md index a6270f58..461dd461 100644 --- a/docs/get.md +++ b/docs/get.md @@ -15,10 +15,24 @@ To build the adapter, you need to install a few dependencies and then execute th * 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. 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? + +We use [semantic versioning](https://semver.org/) (MAJOR.MINOR.PATCH), adapted to the nature of an adapter: + +* As "API" we define the tutorial configuration files. If you would need to update your `preciceDict`, `controlDict` or any other configuration file to keep using your simulation cases with the same OpenFOAM version, this would be a new major version. +* If you could run the same cases without any changes, but you would also get new features or modified behavior (non-trivial), then this would be a new minor version. +* If there would be only bugfixes or trivial changes not affecting the configuration or behavior, then this would be a new patch version. + +Note that the OpenFOAM version is not part of the version of the adapter. It is only reflected in the release archives, which target a range of compatible versions. By default, we support the latest OpenFOAM version from OpenCFD (openfoam.com) and we update our release archives or release a new adapter version (including more than compatibility changes) as soon as there is a new OpenFOAM version. + +Read the [discussion that lead to this versioning strategy](https://github.com/precice/openfoam-adapter/issues/52) for more details. + ## Troubleshooting The following are common problems that may appear during building the OpenFOAM adapter if something went wrong in the described steps. Make sure to always check for error messages at every step before continuing to the next. diff --git a/docs/openfoam-support.md b/docs/openfoam-support.md index 432826fa..b341f1ab 100644 --- a/docs/openfoam-support.md +++ b/docs/openfoam-support.md @@ -7,33 +7,33 @@ 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 v2106 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 v2112 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 v2106: -sudo apt-get install openfoam2106-dev +# Install OpenFOAM v2112: +sudo apt-get install openfoam2112-dev ``` As these steps change your `.profile`, you need to log out and in again to make OpenFOAM fully discoverable. ## Supported OpenFOAM versions -OpenFOAM is a project with long history and many forks, of which we try to support as many as possible. +OpenFOAM is a project with long history and many forks, of which we try to support as many as possible. Since several HPC systems only provide older versions, we try to also support a wide range of versions. -We provide version-specific branches and [release archives](https://github.com/precice/openfoam-adapter/releases/latest) for: +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-v2106](https://github.com/precice/openfoam-adapter) or newer - - [OpenFOAM v1612-v1806](https://github.com/precice/openfoam-adapter/tree/OpenFOAMv1806) + - [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 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 5.x](https://github.com/precice/openfoam-adapter/tree/OpenFOAM5) - - [OpenFOAM 4.0/4.1](https://github.com/precice/openfoam-adapter/tree/OpenFOAM4) + - [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). @@ -133,4 +133,6 @@ However, if you set a *fixed timestep* and *runTimeModifiable*, changing the configured timestep *during the simulation* will not affect the timestep used. A warning will be shown in this case. -{% include disclaimer.html content="This offering is not approved or endorsed by OpenCFD Limited, producer and distributor of the OpenFOAM software via www.openfoam.com, and owner of the OPENFOAM® and OpenCFD® trade marks." %} +{% disclaimer %} +This offering is not approved or endorsed by OpenCFD Limited, producer and distributor of the OpenFOAM software via www.openfoam.com, and owner of the OPENFOAM® and OpenCFD® trade marks. +{% enddisclaimer %} diff --git a/preciceAdapterFunctionObject.H b/preciceAdapterFunctionObject.H index f60aeb35..99f9f5fd 100644 --- a/preciceAdapterFunctionObject.H +++ b/preciceAdapterFunctionObject.H @@ -84,11 +84,11 @@ class preciceAdapterFunctionObject // Private Member Functions - //- Disallow default bitwise copy construct - preciceAdapterFunctionObject(const preciceAdapterFunctionObject&); + //- No copy construct + preciceAdapterFunctionObject(const preciceAdapterFunctionObject&) = delete; - //- Disallow default bitwise assignment - void operator=(const preciceAdapterFunctionObject&); + //- No copy assignment + void operator=(const preciceAdapterFunctionObject&) = delete; public: diff --git a/tools/release_pull_request_template.md b/tools/release_pull_request_template.md new file mode 100644 index 00000000..acbce4f5 --- /dev/null +++ b/tools/release_pull_request_template.md @@ -0,0 +1,81 @@ +# Release checklist + +Copy this template to the release pull request description. + +## Update workflows + +- [ ] `.github/workflows/build.yml` and `.github/workflows/install-dependencies.sh`: Update the OpenFOAM and preCICE versions, if needed. +- [ ] `build-custom.yml`: Add any new OpenFOAM versions and update the default preCICE version, if needed. + +## Prepare branches + +- [ ] Merge `master` to `develop`, if needed +- [ ] Open a pull request from `develop` to `master`. + - We don't use release branches, unless there are changes we don't want to release, potentially when preparing a major release. +- [ ] Run and fix all workflows + +## Test + +- [ ] Run and check flow-over-heated-plate OpenFOAM-OpenFOAM +- [ ] Run and check quickstart +- [ ] Run and check perpendicular-flap OpenFOAM-deal.II +- [ ] Run and check elastic-tube-3d OpenFOAM-CalculiX +- [ ] Run and check partitioned-pipe sonicLiquidFoam-sonicLiquidFoam +- [ ] Run and check heat-exchanger OpenFOAM-CalculiX-OpenFOAM + +Until we get automated system tests again, run all the tests manually. + +## Prepare version-specific branches + +- [ ] Rebase `OpenFOAM4` on `develop` and force-push + - `git checkout OpenFOAM4 && git rebase develop` + - Resolve any conflicts. We should have only one commit in the end. + - `git push --force` +- [ ] Rebase `OpenFOAM5` on `OpenFOAM4`, `OpenFOAM6` on `OpenFOAM5`, ... +- [ ] Trigger a custom build for each version + +Overview of branches: + +```text +master <-- OpenFOAM4 <-- OpenFOAM5 <-- OpenFOAM6 <-- OpenFOAM7 <-- OpenFOAM8 <-- OpenFOAMdev +^-- develop ^-- OpenFOAMv1806 +``` + +## Preparing the Changelog + +- [ ] Copy all the changelog entries into `CHANGELOG.md` +- [ ] Delete `changelog-entries/` +- [ ] Draft and discuss release notes + +## Bump the version + +- [ ] 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). + +## Merge + +- [ ] Review pull request +- [ ] Merge pull request (**not** squash) +- [ ] Rebase the version-specific branches on `master` + +## 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 + - 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` + - branch `OpenFOAM7`: archive `openfoam-adapter_v1.0.0_OpenFOAM7_experimental.tar.gz` + - branch `OpenFOAM8`: archive `openfoam-adapter_v1.0.0_OpenFOAM8_experimental.tar.gz` + +## Post-release + +- [ ] Merge back from `master` to `develop`. No PR is needed for that. +- [ ] Modify the adapter version message to `Loaded the OpenFOAM-preCICE adapter v1.0.0 + unreleased changes`. +- [ ] 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. +- [ ] 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: