diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 4750058f0..486b3b18e 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -10,7 +10,9 @@ TODO
- Add a [sidebar entry](https://github.com/precice/precice.github.io/blob/master/_data/sidebars/tutorial_sidebar.yml)
- Add it to the [overview](https://github.com/precice/precice.github.io/blob/master/content/tutorials/tutorials.md)
+For **release PRs** (new distribution): update `tools/tests/requirements-reference.txt` if `reference_versions.yaml` changed (`python3 tools/tests/update_requirements_reference.py`).
+
## Resources
- [Contributing tutorials](https://precice.org/community-contribute-to-precice.html#contributing-tutorials)
-- [System tests documentation](https://precice.org/dev-docs-system-tests.html)
\ No newline at end of file
+- [System tests documentation](https://precice.org/dev-docs-system-tests.html)
diff --git a/.github/workflows/check-requirements-reference.yml b/.github/workflows/check-requirements-reference.yml
new file mode 100644
index 000000000..15874dcda
--- /dev/null
+++ b/.github/workflows/check-requirements-reference.yml
@@ -0,0 +1,28 @@
+name: Check requirements-reference
+on:
+ push:
+ branches:
+ - master
+ - develop
+ paths:
+ - tools/tests/requirements-reference.txt
+ - tools/tests/reference_versions.yaml
+ - tools/tests/update_requirements_reference.py
+ pull_request:
+ branches:
+ - master
+ - develop
+ paths:
+ - tools/tests/requirements-reference.txt
+ - tools/tests/reference_versions.yaml
+ - tools/tests/update_requirements_reference.py
+jobs:
+ validate:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-python@v5
+ with:
+ python-version: "3.10"
+ - name: Validate requirements-reference
+ run: python3 tools/tests/validate_requirements_reference.py
diff --git a/.github/workflows/generate-reference-results-manual.yml b/.github/workflows/generate-reference-results-manual.yml
new file mode 100644
index 000000000..413223f66
--- /dev/null
+++ b/.github/workflows/generate-reference-results-manual.yml
@@ -0,0 +1,41 @@
+name: Generate reference results (manual)
+on:
+ workflow_dispatch:
+ inputs:
+ suites:
+ description: 'Test suites to execute (comma-separated, see tests.yaml)'
+ default: 'release'
+ required: true
+ type: string
+ from_ref:
+ description: 'Git branch to use and commit to'
+ required: true
+ type: string
+ commit_msg:
+ description: 'Commit message'
+ default: "Add reference results"
+ type: string
+ clean_docker:
+ description: 'Run docker-system-prune before running tests'
+ default: 'FALSE'
+ type: choice
+ options:
+ - 'FALSE'
+ - 'TRUE'
+ log_level:
+ description: 'Logging verbosity of systemtests.py'
+ default: 'INFO'
+ type: choice
+ options:
+ - 'INFO'
+ - 'DEBUG'
+
+jobs:
+ generate_reference_results_manual:
+ uses: ./.github/workflows/generate-reference-results.yml
+ with:
+ from_ref: ${{ inputs.from_ref }}
+ commit_msg: ${{ inputs.commit_msg }}
+ suites: ${{ inputs.suites }}
+ clean_docker: ${{ inputs.clean_docker }}
+ log_level: ${{ inputs.log_level }}
\ No newline at end of file
diff --git a/.github/workflows/generate_reference_results_workflow.yml b/.github/workflows/generate-reference-results.yml
similarity index 63%
rename from .github/workflows/generate_reference_results_workflow.yml
rename to .github/workflows/generate-reference-results.yml
index 6ac87f392..e22e28f63 100644
--- a/.github/workflows/generate_reference_results_workflow.yml
+++ b/.github/workflows/generate-reference-results.yml
@@ -1,35 +1,42 @@
-name: Generate reference results workflow
+name: Generate reference results (called)
on:
workflow_call:
inputs:
- from_ref:
- description: 'Use the systemtests + tutorial metadata + reference_version from this ref'
+ suites:
+ description: 'Test suites to execute (comma-separated, see tests.yaml)'
required: true
type: string
+ from_ref:
+ description: 'Git branch to use and commit to'
+ default: 'develop'
+ type: string
commit_msg:
- description: 'Commit msg for commit that adds the reference results'
- default: "Adding reference results"
+ description: 'Commit message'
+ default: "Add reference results"
type: string
- suites:
- description: 'Comma-separated test suites to generate reference results for. If empty, all suites are generated.'
- default: ''
- required: false
+ clean_docker:
+ description: 'Run docker-system-prune before running tests'
+ default: 'FALSE'
type: string
log_level:
- description: 'Logging verbosity level used for the systemtests'
+ description: 'Logging verbosity of systemtests.py'
required: true
type: string
jobs:
generate_reference_results:
runs-on: [self-hosted, linux, x64, precice-tests-vm]
steps:
- - name: Display a quick job summary
+ - name: Report the input values in the summary
run: |
- echo "Initiated by: ${{ github.actor }}"
- echo "Running generate_reference_results.py --log-level ${{inputs.log_level}}"
- echo "Using Ref: ${{ inputs.from_ref }}"
- echo "Suites filter: ${{ inputs.suites || 'all (no filter)' }}"
- echo "Commit message on success: ${{ inputs.commit_msg }}"
+ {
+ echo "- Initiated by: @${{ github.actor }}"
+ echo "- Test suites: \`${{ inputs.suites || 'all (no filter)' }}\`"
+ echo "- Git branch to commit to: \`${{ inputs.from_ref }}\`"
+ echo "- Commit message: \`${{ inputs.commit_msg }}\`"
+ echo "- Run \`docker-system-prune\` before running tests: \`${{ inputs.clean_docker }}\`"
+ echo "- Log level: \`${{ inputs.log_level }}\`"
+ echo "- Running \`generate_reference_results.py --suite ${{inputs.suites}} --log_level ${{inputs.log_level}}\`"
+ } >> "$GITHUB_STEP_SUMMARY"
- name: Move LFS URL to local LFS server
run: |
/home/precice/runners_root/scripts/make_lfs_local.sh
@@ -51,6 +58,7 @@ jobs:
run: |
pip install --user -r tools/tests/requirements.txt
- name: Cleanup Docker cache
+ if: ${{ inputs.clean_docker == 'TRUE' }}
# Remove all Docker containers, images, and build caches
# to ensure consistent results and as storage cleanup
run: |
@@ -58,14 +66,11 @@ jobs:
- name: Run tests
run: |
cd tools/tests
- test -f generate_reference_results.py && export GENERATE_REF_RESULTS=generate_reference_results.py
- test -f generate_reference_data.py && export GENERATE_REF_RESULTS=generate_reference_data.py
- echo "Selected $GENERATE_REF_RESULTS to run"
SUITES_ARGS=()
if [ -n "${{ inputs.suites }}" ]; then
SUITES_ARGS+=(--suites "${{ inputs.suites }}")
fi
- python "$GENERATE_REF_RESULTS" --log-level="${{inputs.log_level}}" "${SUITES_ARGS[@]}"
+ python generate_reference_results.py --log_level="${{inputs.log_level}}" "${SUITES_ARGS[@]}"
cd ../../
- name: Create commit
if: success()
@@ -84,18 +89,21 @@ jobs:
fi
git commit -m "${{inputs.commit_msg}}"
git push
- - name: Archive run files
- if: failure()
+ - name: Archive system test logs
+ if: ${{ always() }}
uses: actions/upload-artifact@v7
with:
- name: system_tests_run_${{ github.run_id }}_${{ github.run_attempt }}_reference_full
+ name: system_tests_run_${{ github.run_id }}_${{ github.run_attempt }}_reference_logs
path: |
- runs/*
- - name: Archive main log files
+ runs/*/system-tests-build.log
+ runs/*/system-tests-run.log
+ runs/*/system-tests-compare.log
+ runs/*/*/system-tests_*.log
+ - name: Archive run files
+ if: ${{ always() }}
uses: actions/upload-artifact@v7
with:
- name: system_tests_run_${{ github.run_id }}_${{ github.run_attempt }}_reference_logs
+ name: system_tests_run_${{ github.run_id }}_${{ github.run_attempt }}_reference_full
path: |
- runs/*/system-tests-stdout.log
- runs/*/system-tests-stderr.log
- runs/*/*/system-tests_*.log
+ runs/*
+
diff --git a/.github/workflows/generate_reference_results_manual.yml b/.github/workflows/generate_reference_results_manual.yml
deleted file mode 100644
index 5dbcf3f28..000000000
--- a/.github/workflows/generate_reference_results_manual.yml
+++ /dev/null
@@ -1,37 +0,0 @@
-name: Generate reference results (manual)
-on:
- workflow_dispatch:
- inputs:
- from_ref:
- description: 'Use the systemtests + tutorial metadata + reference_version from this ref'
- required: true
- type: string
- commit_msg:
- description: 'Commit msg for commit that adds the reference results'
- default: "Adding reference results"
- type: string
- suites:
- description: 'Comma-separated test suites to generate reference results for (leave empty for all)'
- default: ''
- required: false
- type: string
- log_level:
- description: 'Logging verbosity level used for the systemtests'
- default: 'INFO'
- required: true
- type: choice
- options:
- - 'DEBUG'
- - 'INFO'
- - 'WARNING'
- - 'ERROR'
- - 'CRITICAL'
-
-jobs:
- generate_reference_results_manual:
- uses: ./.github/workflows/generate_reference_results_workflow.yml
- with:
- from_ref: ${{ inputs.from_ref }}
- commit_msg: ${{ inputs.commit_msg }}
- suites: ${{ inputs.suites }}
- log_level: ${{ inputs.log_level }}
\ No newline at end of file
diff --git a/.github/workflows/run_testsuite_manual.yml b/.github/workflows/run_testsuite_manual.yml
deleted file mode 100644
index 5d42ed138..000000000
--- a/.github/workflows/run_testsuite_manual.yml
+++ /dev/null
@@ -1,45 +0,0 @@
-name: Run Testsuite (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:
- suites:
- description: 'Comma seperated testsuites to execute'
- required: true
- type: string
- build_args:
- description: 'Build arguments, if not specified defaults will be taken'
- required: false
- type: string
- system_tests_branch:
- description: 'Branch to take the system tests from (tools/tests/)'
- default: 'develop'
- required: true
- type: string
- log_level:
- description: 'Logging verbosity level used for the systemtests'
- default: 'INFO'
- required: true
- type: choice
- options:
- - 'DEBUG'
- - 'INFO'
- - 'WARNING'
- - 'ERROR'
- - 'CRITICAL'
- upload_artifacts:
- description: 'Upload artifacts also on success (not only on failure)'
- default: 'TRUE'
- type: choice
- options:
- - 'FALSE'
- - 'TRUE'
-
-jobs:
- run_testsuite_manual:
- uses: ./.github/workflows/run_testsuite_workflow.yml
- with:
- suites: ${{ inputs.suites }}
- build_args: ${{ inputs.build_args }}
- system_tests_branch: ${{ inputs.system_tests_branch }}
- log_level: ${{ inputs.log_level }}
- upload_artifacts: ${{ inputs.upload_artifacts }}
diff --git a/.github/workflows/system-tests-latest-components.yml b/.github/workflows/system-tests-latest-components.yml
index a68b8639c..4109768b7 100644
--- a/.github/workflows/system-tests-latest-components.yml
+++ b/.github/workflows/system-tests-latest-components.yml
@@ -1,181 +1,70 @@
-name: System tests (latest components)
+name: System tests (manual/nightly)
on:
schedule:
- cron: "0 4 * * *"
timezone: "Europe/Berlin"
workflow_dispatch:
+ inputs:
+ suites:
+ description: 'Test suites to execute (comma-separated)'
+ default: 'release'
+ required: true
+ type: string
+ system_tests_branch:
+ description: 'Branch to take the system tests from'
+ default: 'develop'
+ type: string
+ ref-precice:
+ description: 'precice Git ref (override latest)'
+ type: string
+ ref-python-bindings:
+ description: 'python-bindings ref'
+ type: string
+ ref-calculix-adapter:
+ description: 'calculix-adapter ref'
+ type: string
+ ref-dealii-adapter:
+ description: 'dealii-adapter ref'
+ type: string
+ ref-dumux-adapter:
+ description: 'dumux-adapter ref'
+ type: string
+ ref-fenics-adapter:
+ description: 'fenics-adapter ref'
+ type: string
+ ref-fenicsx-adapter:
+ description: 'fenicsx-adapter ref'
+ type: string
+ ref-micro-manager:
+ description: 'micro-manager ref'
+ type: string
+ ref-openfoam-adapter:
+ description: 'openfoam-adapter ref'
+ type: string
+ ref-su2-adapter:
+ description: 'su2-adapter ref'
+ type: string
+ ref-tutorials:
+ description: 'tutorials ref'
+ type: string
jobs:
- gather-refs:
- name: Map Git branches to latest refs
- runs-on: ubuntu-latest
- outputs:
- ref-precice: ${{ steps.ref-precice.outputs.shorthash }}
- ref-python-bindings: ${{ steps.ref-python-bindings.outputs.shorthash }}
- ref-calculix-adapter: ${{ steps.ref-calculix-adapter.outputs.shorthash }}
- ref-dumux-adapter: ${{ steps.ref-dumux-adapter.outputs.shorthash }}
- ref-fenics-adapter: ${{ steps.ref-fenics-adapter.outputs.shorthash }}
- ref-micro-manager: ${{ steps.ref-micro-manager.outputs.shorthash }}
- ref-openfoam-adapter: ${{ steps.ref-openfoam-adapter.outputs.shorthash }}
- ref-su2-adapter: ${{ steps.ref-su2-adapter.outputs.shorthash }}
- ref-tutorials: ${{ steps.ref-tutorials.outputs.shorthash }}
- steps:
- - id: ref-precice
- name: Get preCICE ref
- uses: nmbgeek/github-action-get-latest-commit@main
- with:
- owner: precice
- repo: precice
- branch: develop
- - id: ref-python-bindings
- name: Get Python bindings ref
- uses: nmbgeek/github-action-get-latest-commit@main
- with:
- owner: precice
- repo: python-bindings
- branch: develop
- - id: ref-calculix-adapter
- name: Get CalculiX adapter ref
- uses: nmbgeek/github-action-get-latest-commit@main
- with:
- owner: precice
- repo: calculix-adapter
- branch: develop
- - id: ref-dumux-adapter
- name: Get DuMux adapter ref
- uses: nmbgeek/github-action-get-latest-commit@main
- with:
- owner: precice
- repo: dumux-adapter
- branch: develop
- - id: ref-fenics-adapter
- name: Get FEniCS adapter ref
- uses: nmbgeek/github-action-get-latest-commit@main
- with:
- owner: precice
- repo: fenics-adapter
- branch: develop
- - id: ref-micro-manager
- name: Get Micro-Manager ref
- uses: nmbgeek/github-action-get-latest-commit@main
- with:
- owner: precice
- repo: micro-manager
- branch: develop
- - id: ref-openfoam-adapter
- name: Get OpenFOAM adapter ref
- uses: nmbgeek/github-action-get-latest-commit@main
- with:
- owner: precice
- repo: openfoam-adapter
- branch: develop
- - id: ref-su2-adapter
- name: Get SU2 adapter ref
- uses: nmbgeek/github-action-get-latest-commit@main
- with:
- owner: precice
- repo: su2-adapter
- branch: develop
- - id: ref-tutorials
- name: Get tutorials ref
- uses: nmbgeek/github-action-get-latest-commit@main
- with:
- owner: precice
- repo: tutorials
- branch: develop
- - id: report-refs
- name: Report Git refs
- run: |
- printf 'preCICE: ${{ steps.ref-precice.outputs.shorthash }}\n ${{ steps.ref-precice.outputs.description }}\n----------\n'
- printf 'Python bindings: ${{ steps.ref-python-bindings.outputs.shorthash }}\n ${{ steps.ref-python-bindings.outputs.description }}\n----------\n'
- printf 'CalculiX adapter: ${{ steps.ref-calculix-adapter.outputs.shorthash }}\n ${{ steps.ref-calculix-adapter.outputs.description }}\n----------\n'
- printf 'DuMux adapter: ${{ steps.ref-dumux-adapter.outputs.shorthash }}\n ${{ steps.ref-dumux-adapter.outputs.description }}\n----------\n'
- printf 'FEniCS adapter: ${{ steps.ref-fenics-adapter.outputs.shorthash }}\n ${{ steps.ref-fenics-adapter.outputs.description }}\n----------\n'
- printf 'Micro-Manager: ${{ steps.ref-micro-manager.outputs.shorthash }}\n ${{ steps.ref-micro-manager.outputs.description }}\n----------\n'
- printf 'OpenFOAM adapter: ${{ steps.ref-openfoam-adapter.outputs.shorthash }} ${{ steps.ref-openfoam-adapter.outputs.description }}\n----------\n'
- printf 'SU2 adapter: ${{ steps.ref-su2-adapter.outputs.shorthash }}\n ${{ steps.ref-su2-adapter.outputs.description }}\n----------\n'
- printf 'Tutorials: ${{ steps.ref-tutorials.outputs.shorthash }} ${{ steps.ref-tutorials.outputs.description }}\n----------\n'
- - id: summary
- name: Prepare Markdown summary
- run: |
- {
- echo "## Git references of latest (develop) components"
- echo "### preCICE"
- echo "Reference: [\`${{ steps.ref-precice.outputs.shorthash }}\`](https://github.com/precice/precice/commit/${{ steps.ref-precice.outputs.shorthash }})"
- echo "Description:"
- echo "\`\`\`"
- echo "${{ steps.ref-precice.outputs.description }}"
- echo "\`\`\`"
- echo "### Python bindings"
- echo "Reference: [\`${{ steps.ref-python-bindings.outputs.shorthash }}\`](https://github.com/precice/python-bindings/commit/${{ steps.ref-python-bindings.outputs.shorthash }})"
- echo "Description:"
- echo "\`\`\`"
- echo "${{ steps.ref-python-bindings.outputs.description }}"
- echo "\`\`\`"
- echo "### CalculiX adapter"
- echo "Reference: [\`${{ steps.ref-calculix-adapter.outputs.shorthash }}\`](https://github.com/precice/calculix-adapter/commit/${{ steps.ref-calculix-adapter.outputs.shorthash }})"
- echo "Description:"
- echo "\`\`\`"
- echo "${{ steps.ref-calculix-adapter.outputs.description }}"
- echo "\`\`\`"
- echo "### DuMux adapter"
- echo "Reference: [\`${{ steps.ref-dumux-adapter.outputs.shorthash }}\`](https://github.com/precice/dumux-adapter/commit/${{ steps.ref-dumux-adapter.outputs.shorthash }})"
- echo "Description:"
- echo "\`\`\`"
- echo "${{ steps.ref-dumux-adapter.outputs.description }}"
- echo "\`\`\`"
- echo "### FEniCS adapter"
- echo "Reference: [\`${{ steps.ref-fenics-adapter.outputs.shorthash }}\`](https://github.com/precice/fenics-adapter/commit/${{ steps.ref-fenics-adapter.outputs.shorthash }})"
- echo "Description:"
- echo "\`\`\`"
- echo "${{ steps.ref-fenics-adapter.outputs.description }}"
- echo "\`\`\`"
- echo "### Micro-Manager"
- echo "Reference: [\`${{ steps.ref-micro-manager.outputs.shorthash }}\`](https://github.com/precice/micro-manager/commit/${{ steps.ref-micro-manager.outputs.shorthash }})"
- echo "Description:"
- echo "\`\`\`"
- echo "${{ steps.ref-micro-manager.outputs.description }}"
- echo "\`\`\`"
- echo "### OpenFOAM adapter"
- echo "Reference: [\`${{ steps.ref-openfoam-adapter.outputs.shorthash }}\`](https://github.com/precice/openfoam-adapter/commit/${{ steps.ref-openfoam-adapter.outputs.shorthash }})"
- echo "Description:"
- echo "\`\`\`"
- echo "${{ steps.ref-openfoam-adapter.outputs.description }}"
- echo "\`\`\`"
- echo "### SU2 adapter"
- echo "Reference: [\`${{ steps.ref-su2-adapter.outputs.shorthash }}\`](https://github.com/precice/su2-adapter/commit/${{ steps.ref-su2-adapter.outputs.shorthash }})"
- echo "Description:"
- echo "\`\`\`"
- echo "${{ steps.ref-su2-adapter.outputs.description }}"
- echo "\`\`\`"
- echo "### Tutorials"
- echo "Reference: [\`${{ steps.ref-tutorials.outputs.shorthash }}\`](https://github.com/precice/tutorials/commit/${{ steps.ref-tutorials.outputs.shorthash }})"
- echo "Description:"
- echo "\`\`\`"
- echo "${{ steps.ref-tutorials.outputs.description }}"
- echo "\`\`\`"
- } >> "$GITHUB_STEP_SUMMARY"
-
run-system-tests:
name: Trigger system tests
- needs: gather-refs
- uses: precice/tutorials/.github/workflows/run_testsuite_workflow.yml@develop
+ uses: precice/tutorials/.github/workflows/system-tests.yml@develop
with:
- suites: release_test
- build_args: "PLATFORM:ubuntu_2404,\
- PRECICE_REF:${{ needs.gather-refs.outputs.ref-precice }},\
- PYTHON_BINDINGS_REF:${{ needs.gather-refs.outputs.ref-python-bindings }},\
- CALCULIX_VERSION:2.20,\
- CALCULIX_ADAPTER_REF:${{ needs.gather-refs.outputs.ref-calculix-adapter }},\
- DUMUX_VERSION:3.7,\
- DUMUX_ADAPTER_REF:${{ needs.gather-refs.outputs.ref-dumux-adapter }},\
- FENICS_ADAPTER_REF:${{ needs.gather-refs.outputs.ref-fenics-adapter }},\
- MICRO_MANAGER_REF:${{ needs.gather-refs.outputs.ref-micro-manager }},\
- OPENFOAM_EXECUTABLE:openfoam2512,\
- OPENFOAM_ADAPTER_REF:${{ needs.gather-refs.outputs.ref-openfoam-adapter }},\
- SU2_VERSION:7.5.1,\
- SU2_ADAPTER_REF:${{ needs.gather-refs.outputs.ref-su2-adapter }},\
- TUTORIALS_REF:${{ needs.gather-refs.outputs.ref-tutorials }}"
- system_tests_branch: develop
+ suites: ${{ inputs.suites || 'release' }}
+ build_args: "PRECICE_REF:${{ inputs.ref-precice }},\
+ PYTHON_BINDINGS_REF:${{ inputs.ref-python-bindings }},\
+ CALCULIX_ADAPTER_REF:${{ inputs.ref-calculix-adapter }},\
+ DEALII_ADAPTER_REF:${{ inputs.ref-dealii-adapter }},\
+ DUMUX_ADAPTER_REF:${{ inputs.ref-dumux-adapter }},\
+ FENICS_ADAPTER_REF:${{ inputs.ref-fenics-adapter }},\
+ FENICSX_ADAPTER_REF:${{ inputs.ref-fenicsx-adapter }},\
+ MICRO_MANAGER_REF:${{ inputs.ref-micro-manager }},\
+ OPENFOAM_ADAPTER_REF:${{ inputs.ref-openfoam-adapter }},\
+ SU2_ADAPTER_REF:${{ inputs.ref-su2-adapter }},\
+ TUTORIALS_REF:${{ inputs.ref-tutorials }}"
+ system_tests_branch: ${{ inputs.system_tests_branch || 'develop' }}
log_level: "INFO"
diff --git a/.github/workflows/system-tests-pr.yml b/.github/workflows/system-tests-pr.yml
index 39bd92501..a2b28f077 100644
--- a/.github/workflows/system-tests-pr.yml
+++ b/.github/workflows/system-tests-pr.yml
@@ -5,166 +5,10 @@ on:
types: [labeled]
jobs:
- gather-refs:
- name: Map Git branches to latest refs
- if: ${{ github.event.label.name == 'trigger-system-tests' }}
- runs-on: ubuntu-latest
- outputs:
- ref-precice: ${{ steps.ref-precice.outputs.shorthash }}
- ref-python-bindings: ${{ steps.ref-python-bindings.outputs.shorthash }}
- ref-calculix-adapter: ${{ steps.ref-calculix-adapter.outputs.shorthash }}
- ref-dumux-adapter: ${{ steps.ref-dumux-adapter.outputs.shorthash }}
- ref-fenics-adapter: ${{ steps.ref-fenics-adapter.outputs.shorthash }}
- ref-micro-manager: ${{ steps.ref-micro-manager.outputs.shorthash }}
- ref-openfoam-adapter: ${{ steps.ref-openfoam-adapter.outputs.shorthash }}
- ref-su2-adapter: ${{ steps.ref-su2-adapter.outputs.shorthash }}
- steps:
- - id: ref-precice
- name: Get preCICE ref
- uses: nmbgeek/github-action-get-latest-commit@main
- with:
- owner: precice
- repo: precice
- branch: develop
- - id: ref-python-bindings
- name: Get Python bindings ref
- uses: nmbgeek/github-action-get-latest-commit@main
- with:
- owner: precice
- repo: python-bindings
- branch: develop
- - id: ref-calculix-adapter
- name: Get CalculiX adapter ref
- uses: nmbgeek/github-action-get-latest-commit@main
- with:
- owner: precice
- repo: calculix-adapter
- branch: develop
- - id: ref-dumux-adapter
- name: Get DuMux adapter ref
- uses: nmbgeek/github-action-get-latest-commit@main
- with:
- owner: precice
- repo: dumux-adapter
- branch: develop
- - id: ref-fenics-adapter
- name: Get FEniCS adapter ref
- uses: nmbgeek/github-action-get-latest-commit@main
- with:
- owner: precice
- repo: fenics-adapter
- branch: develop
- - id: ref-micro-manager
- name: Get Micro-Manager ref
- uses: nmbgeek/github-action-get-latest-commit@main
- with:
- owner: precice
- repo: micro-manager
- branch: develop
- - id: ref-openfoam-adapter
- name: Get OpenFOAM adapter ref
- uses: nmbgeek/github-action-get-latest-commit@main
- with:
- owner: precice
- repo: openfoam-adapter
- branch: develop
- - id: ref-su2-adapter
- name: Get SU2 adapter ref
- uses: nmbgeek/github-action-get-latest-commit@main
- with:
- owner: precice
- repo: su2-adapter
- branch: develop
- - id: report-refs
- name: Report Git refs
- run: |
- printf 'preCICE: ${{ steps.ref-precice.outputs.shorthash }}\n ${{ steps.ref-precice.outputs.description }}\n----------\n'
- printf 'Python bindings: ${{ steps.ref-python-bindings.outputs.shorthash }}\n ${{ steps.ref-python-bindings.outputs.description }}\n----------\n'
- printf 'CalculiX adapter: ${{ steps.ref-calculix-adapter.outputs.shorthash }}\n ${{ steps.ref-calculix-adapter.outputs.description }}\n----------\n'
- printf 'DuMux adapter: ${{ steps.ref-dumux-adapter.outputs.shorthash }}\n ${{ steps.ref-dumux-adapter.outputs.description }}\n----------\n'
- printf 'FEniCS adapter: ${{ steps.ref-fenics-adapter.outputs.shorthash }}\n ${{ steps.ref-fenics-adapter.outputs.description }}\n----------\n'
- printf 'Micro-Manager: ${{ steps.ref-micro-manager.outputs.shorthash }}\n ${{ steps.ref-micro-manager.outputs.description }}\n----------\n'
- printf 'OpenFOAM adapter: ${{ steps.ref-openfoam-adapter.outputs.shorthash }} ${{ steps.ref-openfoam-adapter.outputs.description }}\n----------\n'
- printf 'SU2 adapter: ${{ steps.ref-su2-adapter.outputs.shorthash }}\n ${{ steps.ref-su2-adapter.outputs.description }}\n----------\n'
- - id: summary
- name: Prepare Markdown summary
- run: |
- {
- echo "## Git references of latest (develop) components"
- echo "### preCICE"
- echo "Reference: [\`${{ steps.ref-precice.outputs.shorthash }}\`](https://github.com/precice/precice/commit/${{ steps.ref-precice.outputs.shorthash }})"
- echo "Description:"
- echo "\`\`\`"
- echo "${{ steps.ref-precice.outputs.description }}"
- echo "\`\`\`"
- echo "### Python bindings"
- echo "Reference: [\`${{ steps.ref-python-bindings.outputs.shorthash }}\`](https://github.com/precice/python-bindings/commit/${{ steps.ref-python-bindings.outputs.shorthash }})"
- echo "Description:"
- echo "\`\`\`"
- echo "${{ steps.ref-python-bindings.outputs.description }}"
- echo "\`\`\`"
- echo "### CalculiX adapter"
- echo "Reference: [\`${{ steps.ref-calculix-adapter.outputs.shorthash }}\`](https://github.com/precice/calculix-adapter/commit/${{ steps.ref-calculix-adapter.outputs.shorthash }})"
- echo "Description:"
- echo "\`\`\`"
- echo "${{ steps.ref-calculix-adapter.outputs.description }}"
- echo "\`\`\`"
- echo "### DuMux adapter"
- echo "Reference: [\`${{ steps.ref-dumux-adapter.outputs.shorthash }}\`](https://github.com/precice/dumux-adapter/commit/${{ steps.ref-dumux-adapter.outputs.shorthash }})"
- echo "Description:"
- echo "\`\`\`"
- echo "${{ steps.ref-dumux-adapter.outputs.description }}"
- echo "\`\`\`"
- echo "### FEniCS adapter"
- echo "Reference: [\`${{ steps.ref-fenics-adapter.outputs.shorthash }}\`](https://github.com/precice/fenics-adapter/commit/${{ steps.ref-fenics-adapter.outputs.shorthash }})"
- echo "Description:"
- echo "\`\`\`"
- echo "${{ steps.ref-fenics-adapter.outputs.description }}"
- echo "\`\`\`"
- echo "### Micro-Manager"
- echo "Reference: [\`${{ steps.ref-micro-manager.outputs.shorthash }}\`](https://github.com/precice/micro-manager/commit/${{ steps.ref-micro-manager.outputs.shorthash }})"
- echo "Description:"
- echo "\`\`\`"
- echo "${{ steps.ref-micro-manager.outputs.description }}"
- echo "\`\`\`"
- echo "### OpenFOAM adapter"
- echo "Reference: [\`${{ steps.ref-openfoam-adapter.outputs.shorthash }}\`](https://github.com/precice/openfoam-adapter/commit/${{ steps.ref-openfoam-adapter.outputs.shorthash }})"
- echo "Description:"
- echo "\`\`\`"
- echo "${{ steps.ref-openfoam-adapter.outputs.description }}"
- echo "\`\`\`"
- echo "### SU2 adapter"
- echo "Reference: [\`${{ steps.ref-su2-adapter.outputs.shorthash }}\`](https://github.com/precice/su2-adapter/commit/${{ steps.ref-su2-adapter.outputs.shorthash }})"
- echo "Description:"
- echo "\`\`\`"
- echo "${{ steps.ref-su2-adapter.outputs.description }}"
- echo "\`\`\`"
- echo "### Tutorials"
- echo "Reference (pull request): \`${{ github.event.pull_request.head.sha }}\`"
- echo "Pull request number: [${{ github.event.number }}](https://github.com/precice/tutorials/pull/${{ github.event.number }})"
- } >> "$GITHUB_STEP_SUMMARY"
-
run-system-tests:
name: Trigger system tests
if: ${{ github.event.label.name == 'trigger-system-tests' }}
- needs: gather-refs
- uses: precice/tutorials/.github/workflows/run_testsuite_workflow.yml@develop
+ uses: precice/tutorials/.github/workflows/system-tests.yml@develop
with:
- suites: release_test
- build_args: "PLATFORM:ubuntu_2404,\
- PRECICE_REF:${{ needs.gather-refs.outputs.ref-precice }},\
- PYTHON_BINDINGS_REF:${{ needs.gather-refs.outputs.ref-python-bindings }},\
- CALCULIX_VERSION:2.20,\
- CALCULIX_ADAPTER_REF:${{ needs.gather-refs.outputs.ref-calculix-adapter }},\
- DUMUX_VERSION:3.7,\
- DUMUX_ADAPTER_REF:${{ needs.gather-refs.outputs.ref-dumux-adapter }},\
- FENICS_ADAPTER_REF:${{ needs.gather-refs.outputs.ref-fenics-adapter }},\
- MICRO_MANAGER_REF:${{ needs.gather-refs.outputs.ref-micro-manager }},\
- OPENFOAM_EXECUTABLE:openfoam2512,\
- OPENFOAM_ADAPTER_REF:${{ needs.gather-refs.outputs.ref-openfoam-adapter }},\
- SU2_VERSION:7.5.1,\
- SU2_ADAPTER_REF:${{ needs.gather-refs.outputs.ref-su2-adapter }},\
- TUTORIALS_PR:${{ github.event.number }},\
- TUTORIALS_REF:${{ github.event.pull_request.head.sha }}"
- system_tests_branch: develop
- log_level: "INFO"
\ No newline at end of file
+ suites: release
+ build_args: "TUTORIALS_REF:${{ github.event.pull_request.head.sha }}"
diff --git a/.github/workflows/run_testsuite_workflow.yml b/.github/workflows/system-tests.yml
similarity index 81%
rename from .github/workflows/run_testsuite_workflow.yml
rename to .github/workflows/system-tests.yml
index 085c5286e..53e6bb0a6 100644
--- a/.github/workflows/run_testsuite_workflow.yml
+++ b/.github/workflows/system-tests.yml
@@ -1,30 +1,28 @@
-name: Run Testsuite reusable workflow
+name: System tests (called)
on:
workflow_call:
inputs:
suites:
- description: 'Comma seperated testsuites to execute'
- required: true
+ description: 'Test suites to execute (comma-separated)'
+ default: 'release'
type: string
build_args:
description: 'Build arguments'
- required: false
type: string
system_tests_branch:
description: 'Branch to take the system tests from'
- required: true
+ default: 'develop'
type: string
log_level:
description: 'Logging verbosity level used for the systemtests'
default: 'INFO'
- required: false
type: string
upload_artifacts:
description: 'TRUE or FALSE (FALSE -> Upload only when the workflow fails)'
default: 'TRUE'
type: string
jobs:
- run_testsuite:
+ run_system_tests:
runs-on: [self-hosted, linux, x64, precice-tests-vm]
steps:
- name: Display a quick job summary
@@ -34,8 +32,9 @@ jobs:
echo "System tests branch (tools/): ${{ inputs.system_tests_branch }}"
echo "System tests log level: ${{ inputs.log_level }}"
echo "Uploading the runs folder on success: ${{ inputs.upload_artifacts }}"
- echo "Running the following command inside tutorials/tools/:"
+ echo "Running the following command inside tutorials/tools/tests/:"
echo "python3 systemtests.py --build_args=${{inputs.build_args}} --suites=${{ inputs.suites}}"
+ echo "All workflow inputs: ${{ toJSON(github.event.inputs) }}"
- name: Prepare the Markdown step summary
run: |
{
@@ -46,10 +45,14 @@ jobs:
echo "- System tests log level: \`${{ inputs.log_level }}\`"
echo "- Uploading the runs folder on success: \`${{ inputs.upload_artifacts }}\`"
echo ""
- echo "Running the following command inside \`tutorials/tools/\`:"
+ echo "Running the following command inside \`tutorials/tools/tests/\`:"
echo "\`\`\`"
echo "python3 systemtests.py --build_args=${{inputs.build_args}} --suites=${{ inputs.suites}}"
echo "\`\`\`"
+ echo "All workflow inputs:"
+ echo "\`\`\`"
+ echo "${{ toJSON(github.event.inputs) }}"
+ echo "\`\`\`"
} >> "$GITHUB_STEP_SUMMARY"
- name: Move LFS URL to local LFS server
run: |
@@ -76,23 +79,22 @@ jobs:
- name: Run tests
run: |
cd tools/tests
- python systemtests.py --build_args=${{ inputs.build_args}} --suites=${{ inputs.suites}} --log-level=${{ inputs.log_level}}
+ python systemtests.py --build_args=${{ inputs.build_args}} --suites=${{ inputs.suites}} --log_level=${{ inputs.log_level}}
cd ../../
- - name: Archive run files
- if: ${{ failure() || inputs.upload_artifacts == 'TRUE' }}
+ - name: Archive system test logs
+ if: ${{ always() }}
uses: actions/upload-artifact@v7
with:
- name: system_tests_run_${{ github.run_id }}_${{ github.run_attempt }}_full
+ name: system_tests_run_${{ github.run_id }}_${{ github.run_attempt }}_logs
path: |
- runs/*
- - name: Archive main log files
+ runs/*/system-tests-build.log
+ runs/*/system-tests-run.log
+ runs/*/system-tests-compare.log
+ runs/*/*/system-tests_*.log
+ - name: Archive run files
+ if: ${{ failure() || inputs.upload_artifacts == 'TRUE' }}
uses: actions/upload-artifact@v7
with:
- name: system_tests_run_${{ github.run_id }}_${{ github.run_attempt }}_logs
+ name: system_tests_run_${{ github.run_id }}_${{ github.run_attempt }}_full
path: |
- runs/*/system-tests-stdout.log
- runs/*/system-tests-stderr.log
- runs/*/*/system-tests_*.log
- - name: tidy up the docker
- run: |
- docker network prune -f
+ runs/*
diff --git a/.gitignore b/.gitignore
index 7f2055b46..1a45bde2a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,7 @@
out
# Common result files
+output/
*.vtk
*.vtu
*.pvd
@@ -24,22 +25,34 @@ profiling.db
profiling.csv
trace.json
profiling.pftrace
+precice-config.xml.orig
# C++
*.o
*.so
.out
+
+# CMake
build/
+CMakeFiles/
+cmake_install.cmake
+CMakeCache.txt
+Makefile
# Python
.venv/
__pycache__/
*.pyc
+*.pyo
# Rust
Cargo.lock
target/
+# Julia
+Manifest.toml
+Project.toml
+
# OpenFOAM
0.*/
[1-9]*/
@@ -54,6 +67,10 @@ postProcessing/
*.foam
*.OpenFOAM
dynamicCode
+Make/*
+!Make/files
+!Make/options
+lnInclude/
# CalculiX
spooles.out
@@ -102,6 +119,9 @@ install*
# G+smo
pointData.csv
+# FMI
+*.fmu
+
# FEniCS covered by .vtk
# Nutils covered by .vtk
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index de5022122..07afb69b3 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -5,7 +5,7 @@ repos:
hooks:
- id: format-precice-config
- repo: https://github.com/igorshubovych/markdownlint-cli
- rev: v0.30.0
+ rev: v0.48.0
hooks:
- id: markdownlint
exclude: ^(.github/pull_request_template.md|changelog-entries)
@@ -22,7 +22,7 @@ repos:
- id: clang-format
exclude: '\.(json|m|mm)$'
- repo: https://github.com/koalaman/shellcheck-precommit
- rev: v0.10.0
+ rev: v0.11.0
hooks:
- id: shellcheck
args: [ --external-sources, --exclude=SC1091 ]
diff --git a/breaking-dam-2d/metadata.yaml b/breaking-dam-2d/metadata.yaml
new file mode 100644
index 000000000..786fc691f
--- /dev/null
+++ b/breaking-dam-2d/metadata.yaml
@@ -0,0 +1,23 @@
+name: Breaking dam 2D
+path: breaking-dam-2d # relative to git repo
+url: https://precice.org/tutorials-breaking-dam-2d.html
+
+participants:
+ - Fluid
+ - Solid
+
+cases:
+ fluid-openfoam:
+ participant: Fluid
+ directory: ./fluid-openfoam
+ run: ./run.sh
+ component: openfoam-adapter
+
+ solid-calculix:
+ participant: Solid
+ directory: ./solid-calculix
+ run: ./run.sh
+ component: calculix-adapter
+
+
+
diff --git a/breaking-dam-2d/reference-results/fluid-openfoam_solid-calculix.tar.gz b/breaking-dam-2d/reference-results/fluid-openfoam_solid-calculix.tar.gz
new file mode 100644
index 000000000..14e88e4e9
--- /dev/null
+++ b/breaking-dam-2d/reference-results/fluid-openfoam_solid-calculix.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0f449e04e0eb4d0fc865f3635f32bf7a293fc47837bb67bd09ee6b525a26b7cf
+size 992246
diff --git a/breaking-dam-2d/reference-results/reference_results.metadata b/breaking-dam-2d/reference-results/reference_results.metadata
new file mode 100644
index 000000000..a182e9086
--- /dev/null
+++ b/breaking-dam-2d/reference-results/reference_results.metadata
@@ -0,0 +1,71 @@
+
+
+# Reference Results
+
+This file contains an overview of the results over the reference results as well as the arguments used to generate them.
+We also include some information on the machine used to generate them
+
+## List of files
+
+| name | time | sha256 |
+|------|------|-------|
+| fluid-openfoam_solid-calculix.tar.gz | 2026-05-30 20:40:55 | 0f449e04e0eb4d0fc865f3635f32bf7a293fc47837bb67bd09ee6b525a26b7cf |
+
+## List of arguments used to generate the files
+
+| name | value |
+|------|------|
+| PLATFORM | ubuntu_2404 |
+| CALCULIX_VERSION | 2.20 |
+| DUNE_VERSION | 2.9 |
+| DUMUX_VERSION | 3.7 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | more-tests |
+| PRECICE_PRESET | production-audit |
+| PRECICE_UID | 1003 |
+| PRECICE_GID | 1003 |
+## Information about the machine
+
+### uname -a
+
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+
+
+### lscpu
+
+Architecture: x86_64
+CPU op-mode(s): 32-bit, 64-bit
+Address sizes: 45 bits physical, 48 bits virtual
+Byte Order: Little Endian
+CPU(s): 4
+On-line CPU(s) list: 0-3
+Vendor ID: GenuineIntel
+Model name: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz
+CPU family: 6
+Model: 85
+Thread(s) per core: 1
+Core(s) per socket: 1
+Socket(s): 4
+Stepping: 4
+BogoMIPS: 4199.99
+Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat pku ospke md_clear flush_l1d arch_capabilities
+Hypervisor vendor: VMware
+Virtualization type: full
+L1d cache: 128 KiB (4 instances)
+L1i cache: 128 KiB (4 instances)
+L2 cache: 4 MiB (4 instances)
+L3 cache: 88 MiB (4 instances)
+NUMA node(s): 1
+NUMA node0 CPU(s): 0-3
diff --git a/changelog-entries/610.md b/changelog-entries/610.md
new file mode 100644
index 000000000..dc7b62a95
--- /dev/null
+++ b/changelog-entries/610.md
@@ -0,0 +1 @@
+- Add `requirements-reference.txt` (lockfile-style pinned Python versions) and `update_requirements_reference.py` for reproducible dependency versions per distribution (fixes [#610](https://github.com/precice/tutorials/issues/610)). Includes GitHub Action to validate pyprecice version matches `reference_versions.yaml`; release PR template reminder to update the reference file.
diff --git a/changelog-entries/654.md b/changelog-entries/654.md
new file mode 100644
index 000000000..12b0bee1a
--- /dev/null
+++ b/changelog-entries/654.md
@@ -0,0 +1 @@
+- Added tools/run-foam-extend.sh to modify OpenFOAM tutorials for foam-extend and made the Quickstart tutorial compatible with foam-extend [#654](https://github.com/precice/tutorials/pull/654).
\ No newline at end of file
diff --git a/changelog-entries/658.md b/changelog-entries/658.md
new file mode 100644
index 000000000..cf9e728c7
--- /dev/null
+++ b/changelog-entries/658.md
@@ -0,0 +1 @@
+- Added Julia-based participants to the resonant-circuit tutorial [#658](https://github.com/precice/tutorials/pull/658)
\ No newline at end of file
diff --git a/changelog-entries/708.md b/changelog-entries/708.md
new file mode 100644
index 000000000..26fc5b820
--- /dev/null
+++ b/changelog-entries/708.md
@@ -0,0 +1 @@
+- Added the flow-over-heated-plate-two-meshes case to the system tests [#708](https://github.com/precice/tutorials/pull/708)
\ No newline at end of file
diff --git a/changelog-entries/714.md b/changelog-entries/714.md
new file mode 100644
index 000000000..f1f0fc71c
--- /dev/null
+++ b/changelog-entries/714.md
@@ -0,0 +1 @@
+- Added a 3D partitioned heat conduction tutorial with FEniCSx [#714](https://github.com/precice/tutorials/pull/714)
\ No newline at end of file
diff --git a/changelog-entries/749.md b/changelog-entries/749.md
new file mode 100644
index 000000000..49bb2bf73
--- /dev/null
+++ b/changelog-entries/749.md
@@ -0,0 +1 @@
+- Add loose version constraints to tutorial `requirements.txt` files and `tools/report_tutorial_requirements.py` to generate a root-level `requirements-reference.txt` snapshot from PyPI at release time (fixes [#610](https://github.com/precice/tutorials/issues/610)). Includes GitHub Action to validate the reference file stays in sync.
diff --git a/changelog-entries/793.md b/changelog-entries/793.md
new file mode 100644
index 000000000..7dc2bfa6d
--- /dev/null
+++ b/changelog-entries/793.md
@@ -0,0 +1 @@
+- Added the `wolf-sheep-soil-creep` tutorial [#793](https://github.com/precice/tutorials/pull/793)
\ No newline at end of file
diff --git a/changelog-entries/799.md b/changelog-entries/799.md
new file mode 100644
index 000000000..12874ffc3
--- /dev/null
+++ b/changelog-entries/799.md
@@ -0,0 +1 @@
+- Restructured the list of system tests. Repositories triggering a test suite besides the `release_test` need to be updated. [#799](https://github.com/precice/tutorials/pull/799)
\ No newline at end of file
diff --git a/changelog-entries/801.md b/changelog-entries/801.md
new file mode 100644
index 000000000..745806f4a
--- /dev/null
+++ b/changelog-entries/801.md
@@ -0,0 +1 @@
+- System tests now write logs during each run (build, run, compare), including `system-tests-build.log`, `system-tests-run.log`, and `system-tests-compare.log` [#801](https://github.com/precice/tutorials/pull/801).
diff --git a/changelog-entries/802.md b/changelog-entries/802.md
new file mode 100644
index 000000000..c9a8badcb
--- /dev/null
+++ b/changelog-entries/802.md
@@ -0,0 +1 @@
+- Changed the system tests reference results format from VTK to VTU [#802](https://github.com/precice/tutorials/pull/802)
\ No newline at end of file
diff --git a/changelog-entries/805.md b/changelog-entries/805.md
new file mode 100644
index 000000000..fa3cf0946
--- /dev/null
+++ b/changelog-entries/805.md
@@ -0,0 +1 @@
+- Removed the heat-exchanger/download-meshes.sh script. The meshes are now automatically downloaded by each run.sh script. [#805](https://github.com/precice/tutorials/pull/805)
\ No newline at end of file
diff --git a/changelog-entries/806.md b/changelog-entries/806.md
new file mode 100644
index 000000000..c2436149d
--- /dev/null
+++ b/changelog-entries/806.md
@@ -0,0 +1 @@
+- Added the heat-exchanger tutorial to the system tests [#806](https://github.com/precice/tutorials/pull/806)
\ No newline at end of file
diff --git a/changelog-entries/810.md b/changelog-entries/810.md
new file mode 100644
index 000000000..93f67102c
--- /dev/null
+++ b/changelog-entries/810.md
@@ -0,0 +1 @@
+- Automated the execution of the sonicliquidfoam participants in the partitioned-pipe tutorial. Manually editing the precice-config.xml is no longer required to run these cases. [#810](https://github.com/precice/tutorials/pull/810)
\ No newline at end of file
diff --git a/changelog-entries/812.md b/changelog-entries/812.md
new file mode 100644
index 000000000..aeaed428c
--- /dev/null
+++ b/changelog-entries/812.md
@@ -0,0 +1 @@
+- Removed obsolete version default overrides in the system tests CI workflows [#812](https://github.com/precice/tutorials/pull/812).
\ No newline at end of file
diff --git a/changelog-entries/814.md b/changelog-entries/814.md
new file mode 100644
index 000000000..aa90298ef
--- /dev/null
+++ b/changelog-entries/814.md
@@ -0,0 +1 @@
+- Renamed the data, meshes, and participants in the partitioned-elastic-beam tutorial [#814](https://github.com/precice/tutorials/pull/814)
\ No newline at end of file
diff --git a/changelog-entries/816.md b/changelog-entries/816.md
new file mode 100644
index 000000000..973817a0c
--- /dev/null
+++ b/changelog-entries/816.md
@@ -0,0 +1 @@
+- Renamed the `Flow` participant to `Fluid` in the channel-transport-reaction tutorial [#816](https://github.com/precice/tutorials/pull/816)
\ No newline at end of file
diff --git a/changelog-entries/820.md b/changelog-entries/820.md
new file mode 100644
index 000000000..af1ddb10d
--- /dev/null
+++ b/changelog-entries/820.md
@@ -0,0 +1 @@
+- The system tests now call `docker network prune` on the host before and after executing a test [#820](https://github.com/precice/tutorials/pull/820)
\ No newline at end of file
diff --git a/changelog-entries/823.md b/changelog-entries/823.md
new file mode 100644
index 000000000..f5c6e7e8e
--- /dev/null
+++ b/changelog-entries/823.md
@@ -0,0 +1 @@
+- Updated the elastic-tube-1d fortran-module cases to download the fortran-module into `thirdparty/` [#823](https://github.com/precice/tutorials/pull/823)
\ No newline at end of file
diff --git a/changelog-entries/830.md b/changelog-entries/830.md
new file mode 100644
index 000000000..d481a1e90
--- /dev/null
+++ b/changelog-entries/830.md
@@ -0,0 +1 @@
+- Failed system tests now append the last lines of the relevant stage log to the GitHub Actions job summary [#830](https://github.com/precice/tutorials/pull/830).
diff --git a/changelog-entries/842.md b/changelog-entries/842.md
new file mode 100644
index 000000000..188405b7a
--- /dev/null
+++ b/changelog-entries/842.md
@@ -0,0 +1 @@
+- Moved the resolution of latest commits from the CI workflows to the `Systemtest.py`. Workflows of other repositories that trigger this one can now only specify the build arguments that are needed. [#842](https://github.com/precice/tutorials/pull/842)
diff --git a/changelog-entries/843.md b/changelog-entries/843.md
new file mode 100644
index 000000000..7b1a24b30
--- /dev/null
+++ b/changelog-entries/843.md
@@ -0,0 +1 @@
+- Renamed the system tests GitHub Actions workflows [#843](https://github.com/precice/tutorials/pull/843)
\ No newline at end of file
diff --git a/channel-transport-particles/.gitignore b/channel-transport-particles/.gitignore
new file mode 100644
index 000000000..d98835264
--- /dev/null
+++ b/channel-transport-particles/.gitignore
@@ -0,0 +1,2 @@
+# Signal file expected by the system tests specifically in uni-directional coupling
+particles-participant-finished.log
\ No newline at end of file
diff --git a/channel-transport-particles/README.md b/channel-transport-particles/README.md
index d6725e66c..24e090e9d 100644
--- a/channel-transport-particles/README.md
+++ b/channel-transport-particles/README.md
@@ -28,7 +28,7 @@ preCICE configuration (image generated using the [precice-config-visualizer](htt
Fluid participant:
-* Nutils. For more information, have a look at the [Nutils adapter documentation](https://precice.org/adapter-nutils.html). This Nutils solver requires at least Nutils v7.0.
+* Nutils. For more information, have a look at the [Nutils adapter documentation](https://precice.org/adapter-nutils.html).
* OpenFOAM (pimpleFoam). For more information, have a look at the [OpenFOAM adapter documentation](https://precice.org/adapter-openfoam-overview.html).
diff --git a/channel-transport-particles/fluid-nutils/requirements.txt b/channel-transport-particles/fluid-nutils/requirements.txt
index e535d45e9..5b7dc1cf6 100644
--- a/channel-transport-particles/fluid-nutils/requirements.txt
+++ b/channel-transport-particles/fluid-nutils/requirements.txt
@@ -1,5 +1,5 @@
-setuptools # required by nutils
+setuptools>=69.0.0 # required by nutils
nutils~=7.3
numpy >1, <2
pyprecice~=3.0
-setuptools
+setuptools>=69.0.0
diff --git a/channel-transport-particles/fluid-nutils/run.sh b/channel-transport-particles/fluid-nutils/run.sh
index 641f4f465..06296eb27 100755
--- a/channel-transport-particles/fluid-nutils/run.sh
+++ b/channel-transport-particles/fluid-nutils/run.sh
@@ -4,13 +4,24 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
python3 fluid.py
+# System tests: Keep the container and the respective network alive till the end.
+if [[ -v PRECICE_TUTORIALS_TESTING ]]; then
+ echo "Waiting for the Particles participant to finish..."
+ if [ ! -f "../particles-participant-finished.log" ]; then
+ inotifywait -e create,modify,attrib --include '/particles-participant-finished\.log$' -qq ..
+ fi
+fi
+
close_log
diff --git a/channel-transport-particles/fluid-openfoam/run.sh b/channel-transport-particles/fluid-openfoam/run.sh
index 8f55fbfa5..1ca8bf096 100755
--- a/channel-transport-particles/fluid-openfoam/run.sh
+++ b/channel-transport-particles/fluid-openfoam/run.sh
@@ -9,4 +9,12 @@ blockMesh
../../tools/run-openfoam.sh "$@"
. ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs
+# System tests: Keep the container and the respective network alive till the end.
+if [[ -v PRECICE_TUTORIALS_TESTING ]]; then
+ echo "Waiting for the Particles participant to finish..."
+ if [ ! -f "../particles-participant-finished.log" ]; then
+ inotifywait -e create,modify,attrib --include '/particles-participant-finished\.log$' -qq ..
+ fi
+fi
+
close_log
diff --git a/channel-transport-particles/metadata.yaml b/channel-transport-particles/metadata.yaml
new file mode 100644
index 000000000..1fbf0a728
--- /dev/null
+++ b/channel-transport-particles/metadata.yaml
@@ -0,0 +1,26 @@
+name: Channel transport particles
+path: channel-transport-particles
+url: https://precice.org/tutorials-channel-transport-particles.html
+
+participants:
+ - Fluid
+ - Particles
+
+cases:
+ fluid-nutils:
+ participant: Fluid
+ directory: ./fluid-nutils
+ run: ./run.sh
+ component: nutils-adapter
+
+ fluid-openfoam:
+ participant: Fluid
+ directory: ./fluid-openfoam
+ run: ./run.sh
+ component: openfoam-adapter
+
+ particles-mercurydpm:
+ participant: Particles
+ directory: ./particles-mercurydpm
+ run: ./run.sh
+ component: mercurydpm-adapter
\ No newline at end of file
diff --git a/channel-transport-particles/particles-mercurydpm/.gitignore b/channel-transport-particles/particles-mercurydpm/.gitignore
new file mode 100644
index 000000000..ac2210f18
--- /dev/null
+++ b/channel-transport-particles/particles-mercurydpm/.gitignore
@@ -0,0 +1 @@
+ChannelTransport*
\ No newline at end of file
diff --git a/channel-transport-particles/particles-mercurydpm/run.sh b/channel-transport-particles/particles-mercurydpm/run.sh
index 3fa37bf74..f9f51b999 100755
--- a/channel-transport-particles/particles-mercurydpm/run.sh
+++ b/channel-transport-particles/particles-mercurydpm/run.sh
@@ -1,5 +1,8 @@
#!/usr/bin/env bash
-set -euo pipefail
+set -e -u -o pipefail
+
+. ../../tools/log.sh
+exec > >(tee --append "$LOGFILE") 2>&1
EXE=""
MERCURYDPM_BUILD_DIR="${MERCURYDPM_BUILD_DIR:-}"
@@ -45,6 +48,12 @@ run_and_exit() {
local cmd="$1"
log "Using executable: ${cmd}"
"${cmd}"
+
+ # Necessary signal file for the system tests,
+ # to keep the Source container running till the end
+ date > ../particles-participant-finished.log
+
+ close_log
exit 0
}
@@ -102,4 +111,5 @@ Hints:
- MercuryDPM must be built with preCICE coupling:
-D MercuryDPM_PreCICE_COUPLING="ON"
EOF
+close_log
exit 1
diff --git a/channel-transport-particles/particles-mercurydpm/setup-mercurydpm.sh b/channel-transport-particles/particles-mercurydpm/setup-mercurydpm.sh
old mode 100644
new mode 100755
diff --git a/channel-transport-particles/reference-results/fluid-nutils_particles-mercurydpm.tar.gz b/channel-transport-particles/reference-results/fluid-nutils_particles-mercurydpm.tar.gz
new file mode 100644
index 000000000..a3fba4168
--- /dev/null
+++ b/channel-transport-particles/reference-results/fluid-nutils_particles-mercurydpm.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a1a0ddf28692ca1e01b65150ba4a44c376fa13c076a755305519408c8e5710cc
+size 781206
diff --git a/channel-transport-particles/reference-results/fluid-openfoam_particles-mercurydpm.tar.gz b/channel-transport-particles/reference-results/fluid-openfoam_particles-mercurydpm.tar.gz
new file mode 100644
index 000000000..285c1c22c
--- /dev/null
+++ b/channel-transport-particles/reference-results/fluid-openfoam_particles-mercurydpm.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:32dcaac90e5ca724fe73443e8e244a7eb0f73b03c9f33df8b0d8860a7b3a5e5f
+size 93601
diff --git a/channel-transport-particles/reference-results/reference_results.metadata b/channel-transport-particles/reference-results/reference_results.metadata
new file mode 100644
index 000000000..b3311dbc3
--- /dev/null
+++ b/channel-transport-particles/reference-results/reference_results.metadata
@@ -0,0 +1,73 @@
+
+
+# Reference Results
+
+This file contains an overview of the results over the reference results as well as the arguments used to generate them.
+We also include some information on the machine used to generate them
+
+## List of files
+
+| name | time | sha256 |
+|------|------|-------|
+| fluid-openfoam_particles-mercurydpm.tar.gz | 2026-06-13 16:50:21 | 32dcaac90e5ca724fe73443e8e244a7eb0f73b03c9f33df8b0d8860a7b3a5e5f |
+| fluid-nutils_particles-mercurydpm.tar.gz | 2026-06-13 16:50:21 | a1a0ddf28692ca1e01b65150ba4a44c376fa13c076a755305519408c8e5710cc |
+
+## List of arguments used to generate the files
+
+| name | value |
+|------|------|
+| PLATFORM | ubuntu_2404 |
+| CALCULIX_VERSION | 2.20 |
+| DUNE_VERSION | 2.9 |
+| DUMUX_VERSION | 3.7 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| FENICSX_ADAPTER_REF | v1.0.1 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | mercurydpm-tests |
+| PRECICE_PRESET | production-audit |
+| PRECICE_UID | 1003 |
+| PRECICE_GID | 1003 |
+## Information about the machine
+
+### uname -a
+
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+
+
+### lscpu
+
+Architecture: x86_64
+CPU op-mode(s): 32-bit, 64-bit
+Address sizes: 45 bits physical, 48 bits virtual
+Byte Order: Little Endian
+CPU(s): 4
+On-line CPU(s) list: 0-3
+Vendor ID: GenuineIntel
+Model name: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz
+CPU family: 6
+Model: 85
+Thread(s) per core: 1
+Core(s) per socket: 1
+Socket(s): 4
+Stepping: 4
+BogoMIPS: 4199.99
+Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat pku ospke md_clear flush_l1d arch_capabilities
+Hypervisor vendor: VMware
+Virtualization type: full
+L1d cache: 128 KiB (4 instances)
+L1i cache: 128 KiB (4 instances)
+L2 cache: 4 MiB (4 instances)
+L3 cache: 88 MiB (4 instances)
+NUMA node(s): 1
+NUMA node0 CPU(s): 0-3
diff --git a/channel-transport-reaction/chemical-fenics/run.sh b/channel-transport-reaction/chemical-fenics/run.sh
index e0927a968..51fe70d0d 100755
--- a/channel-transport-reaction/chemical-fenics/run.sh
+++ b/channel-transport-reaction/chemical-fenics/run.sh
@@ -4,11 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv --system-site-package .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv --system-site-packages .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
python3 chemical-reaction-advection-diffusion.py
diff --git a/channel-transport-reaction/fluid-fenics/fluid-config.json b/channel-transport-reaction/fluid-fenics/fluid-config.json
index f3a828ae3..7f186e509 100644
--- a/channel-transport-reaction/fluid-fenics/fluid-config.json
+++ b/channel-transport-reaction/fluid-fenics/fluid-config.json
@@ -1,8 +1,8 @@
{
- "participant_name": "Flow",
+ "participant_name": "Fluid",
"config_file_name": "../precice-config.xml",
"interface": {
- "coupling_mesh_name": "Flow-Mesh",
+ "coupling_mesh_name": "Fluid-Mesh",
"write_data_name": "Velocity"
}
}
diff --git a/channel-transport-reaction/fluid-fenics/run.sh b/channel-transport-reaction/fluid-fenics/run.sh
index ff60931b0..4df22d92b 100755
--- a/channel-transport-reaction/fluid-fenics/run.sh
+++ b/channel-transport-reaction/fluid-fenics/run.sh
@@ -4,11 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv --system-site-package .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv --system-site-packages .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
python3 fluid.py
diff --git a/channel-transport-reaction/images/tutorials-channel-transport-reaction-precice-config.png b/channel-transport-reaction/images/tutorials-channel-transport-reaction-precice-config.png
index e401822ac..8d8d51f2e 100644
Binary files a/channel-transport-reaction/images/tutorials-channel-transport-reaction-precice-config.png and b/channel-transport-reaction/images/tutorials-channel-transport-reaction-precice-config.png differ
diff --git a/channel-transport-reaction/metadata.yaml b/channel-transport-reaction/metadata.yaml
new file mode 100644
index 000000000..89e96fe1b
--- /dev/null
+++ b/channel-transport-reaction/metadata.yaml
@@ -0,0 +1,20 @@
+name: Channel transport reaction
+path: channel-transport-reaction
+url: https://precice.org/tutorials-channel-transport-reaction.html
+
+participants:
+ - Fluid
+ - Chemical
+
+cases:
+ fluid-fenics:
+ participant: Fluid
+ directory: ./fluid-fenics
+ run: ./run.sh
+ component: fenics-adapter
+
+ chemical-fenics:
+ participant: Chemical
+ directory: ./chemical-fenics
+ run: ./run.sh
+ component: fenics-adapter
\ No newline at end of file
diff --git a/channel-transport-reaction/precice-config.xml b/channel-transport-reaction/precice-config.xml
index cb2dad98f..ee38c33bf 100644
--- a/channel-transport-reaction/precice-config.xml
+++ b/channel-transport-reaction/precice-config.xml
@@ -11,7 +11,7 @@
-
+
@@ -19,28 +19,28 @@
-
-
-
+
+
+
-
+
-
+
-
+
-
+
diff --git a/channel-transport-reaction/reference-results/fluid-fenics_chemical-fenics.tar.gz b/channel-transport-reaction/reference-results/fluid-fenics_chemical-fenics.tar.gz
new file mode 100644
index 000000000..f36a95625
--- /dev/null
+++ b/channel-transport-reaction/reference-results/fluid-fenics_chemical-fenics.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f736db2462a64dbe5b978d05c0fa3fb46c883f909bf40c80f6710c16c93547a5
+size 1500169
diff --git a/channel-transport-reaction/reference-results/reference_results.metadata b/channel-transport-reaction/reference-results/reference_results.metadata
new file mode 100644
index 000000000..55d741d19
--- /dev/null
+++ b/channel-transport-reaction/reference-results/reference_results.metadata
@@ -0,0 +1,71 @@
+
+
+# Reference Results
+
+This file contains an overview of the results over the reference results as well as the arguments used to generate them.
+We also include some information on the machine used to generate them
+
+## List of files
+
+| name | time | sha256 |
+|------|------|-------|
+| fluid-fenics_chemical-fenics.tar.gz | 2026-05-29 09:34:06 | f736db2462a64dbe5b978d05c0fa3fb46c883f909bf40c80f6710c16c93547a5 |
+
+## List of arguments used to generate the files
+
+| name | value |
+|------|------|
+| PLATFORM | ubuntu_2404 |
+| CALCULIX_VERSION | 2.20 |
+| DUNE_VERSION | 2.9 |
+| DUMUX_VERSION | 3.7 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | bf5323c |
+| PRECICE_PRESET | production-audit |
+| PRECICE_UID | 1003 |
+| PRECICE_GID | 1003 |
+## Information about the machine
+
+### uname -a
+
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+
+
+### lscpu
+
+Architecture: x86_64
+CPU op-mode(s): 32-bit, 64-bit
+Address sizes: 45 bits physical, 48 bits virtual
+Byte Order: Little Endian
+CPU(s): 4
+On-line CPU(s) list: 0-3
+Vendor ID: GenuineIntel
+Model name: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz
+CPU family: 6
+Model: 85
+Thread(s) per core: 1
+Core(s) per socket: 1
+Socket(s): 4
+Stepping: 4
+BogoMIPS: 4199.99
+Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat pku ospke md_clear flush_l1d arch_capabilities
+Hypervisor vendor: VMware
+Virtualization type: full
+L1d cache: 128 KiB (4 instances)
+L1i cache: 128 KiB (4 instances)
+L2 cache: 4 MiB (4 instances)
+L3 cache: 88 MiB (4 instances)
+NUMA node(s): 1
+NUMA node0 CPU(s): 0-3
diff --git a/channel-transport/README.md b/channel-transport/README.md
index a929c4acb..efa81fa12 100644
--- a/channel-transport/README.md
+++ b/channel-transport/README.md
@@ -37,13 +37,13 @@ preCICE configuration (image generated using the [precice-config-visualizer](htt
Fluid participant:
-* Nutils. For more information, have a look at the [Nutils adapter documentation](https://precice.org/adapter-nutils.html). This Nutils solver requires at least Nutils v7.0.
+* Nutils. For more information, have a look at the [Nutils adapter documentation](https://precice.org/adapter-nutils.html).
* OpenFOAM (pimpleFoam). For more information, have a look at the [OpenFOAM adapter documentation](https://precice.org/adapter-openfoam-overview.html).
Transport participant:
-* Nutils with support for [adaptive mesh refinement](https://precice.org/couple-your-code-moving-or-changing-meshes.html#pseudo-reference-domain). For more information, have a look at the [Nutils adapter documentation](https://precice.org/adapter-nutils.html). This Nutils solver requires at least Nutils v7.0 and a preCICE release with [remeshing support](couple-your-code-moving-or-changing-meshes.html#remeshing-using-precice).
+* Nutils with support for [adaptive mesh refinement](https://precice.org/couple-your-code-moving-or-changing-meshes.html#pseudo-reference-domain). For more information, have a look at the [Nutils adapter documentation](https://precice.org/adapter-nutils.html). This solver requires a preCICE release with [remeshing support](couple-your-code-moving-or-changing-meshes.html#remeshing-using-precice).
## Running the simulation
diff --git a/channel-transport/fluid-nutils/requirements.txt b/channel-transport/fluid-nutils/requirements.txt
index e535d45e9..5b7dc1cf6 100644
--- a/channel-transport/fluid-nutils/requirements.txt
+++ b/channel-transport/fluid-nutils/requirements.txt
@@ -1,5 +1,5 @@
-setuptools # required by nutils
+setuptools>=69.0.0 # required by nutils
nutils~=7.3
numpy >1, <2
pyprecice~=3.0
-setuptools
+setuptools>=69.0.0
diff --git a/channel-transport/fluid-nutils/run.sh b/channel-transport/fluid-nutils/run.sh
index 641f4f465..8fa22ebdb 100755
--- a/channel-transport/fluid-nutils/run.sh
+++ b/channel-transport/fluid-nutils/run.sh
@@ -4,11 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
python3 fluid.py
diff --git a/channel-transport/metadata.yaml b/channel-transport/metadata.yaml
new file mode 100644
index 000000000..72588003e
--- /dev/null
+++ b/channel-transport/metadata.yaml
@@ -0,0 +1,26 @@
+name: Channel transport
+path: channel-transport
+url: https://precice.org/tutorials-channel-transport.html
+
+participants:
+ - Fluid
+ - Transport
+
+cases:
+ fluid-openfoam:
+ participant: Fluid
+ directory: ./fluid-openfoam
+ run: ./run.sh
+ component: openfoam-adapter
+
+ fluid-nutils:
+ participant: Fluid
+ directory: ./fluid-nutils
+ run: ./run.sh
+ component: nutils-adapter
+
+ transport-nutils:
+ participant: Transport
+ directory: ./transport-nutils
+ run: ./run.sh
+ component: nutils-adapter
\ No newline at end of file
diff --git a/channel-transport/reference-results/fluid-nutils_transport-nutils.tar.gz b/channel-transport/reference-results/fluid-nutils_transport-nutils.tar.gz
new file mode 100644
index 000000000..0ca0d040e
--- /dev/null
+++ b/channel-transport/reference-results/fluid-nutils_transport-nutils.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:88f14284c484db5e806a884bb6cddee4e583607cb71f01a3d6f367d6125a7aaa
+size 1610585
diff --git a/channel-transport/reference-results/fluid-openfoam_transport-nutils.tar.gz b/channel-transport/reference-results/fluid-openfoam_transport-nutils.tar.gz
new file mode 100644
index 000000000..cc103856d
--- /dev/null
+++ b/channel-transport/reference-results/fluid-openfoam_transport-nutils.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:8ba1c8e6b8f1d7363189ece66db2ab5f0a88398a770c79736fb121d4ea3ecf6e
+size 1818514
diff --git a/channel-transport/reference-results/reference_results.metadata b/channel-transport/reference-results/reference_results.metadata
new file mode 100644
index 000000000..936b235de
--- /dev/null
+++ b/channel-transport/reference-results/reference_results.metadata
@@ -0,0 +1,72 @@
+
+
+# Reference Results
+
+This file contains an overview of the results over the reference results as well as the arguments used to generate them.
+We also include some information on the machine used to generate them
+
+## List of files
+
+| name | time | sha256 |
+|------|------|-------|
+| fluid-nutils_transport-nutils.tar.gz | 2026-05-29 09:34:06 | 88f14284c484db5e806a884bb6cddee4e583607cb71f01a3d6f367d6125a7aaa |
+| fluid-openfoam_transport-nutils.tar.gz | 2026-05-29 09:34:06 | 8ba1c8e6b8f1d7363189ece66db2ab5f0a88398a770c79736fb121d4ea3ecf6e |
+
+## List of arguments used to generate the files
+
+| name | value |
+|------|------|
+| PLATFORM | ubuntu_2404 |
+| CALCULIX_VERSION | 2.20 |
+| DUNE_VERSION | 2.9 |
+| DUMUX_VERSION | 3.7 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | bf5323c |
+| PRECICE_PRESET | production-audit |
+| PRECICE_UID | 1003 |
+| PRECICE_GID | 1003 |
+## Information about the machine
+
+### uname -a
+
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+
+
+### lscpu
+
+Architecture: x86_64
+CPU op-mode(s): 32-bit, 64-bit
+Address sizes: 45 bits physical, 48 bits virtual
+Byte Order: Little Endian
+CPU(s): 4
+On-line CPU(s) list: 0-3
+Vendor ID: GenuineIntel
+Model name: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz
+CPU family: 6
+Model: 85
+Thread(s) per core: 1
+Core(s) per socket: 1
+Socket(s): 4
+Stepping: 4
+BogoMIPS: 4199.99
+Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat pku ospke md_clear flush_l1d arch_capabilities
+Hypervisor vendor: VMware
+Virtualization type: full
+L1d cache: 128 KiB (4 instances)
+L1i cache: 128 KiB (4 instances)
+L2 cache: 4 MiB (4 instances)
+L3 cache: 88 MiB (4 instances)
+NUMA node(s): 1
+NUMA node0 CPU(s): 0-3
diff --git a/channel-transport/transport-nutils/requirements.txt b/channel-transport/transport-nutils/requirements.txt
index 0473bd5c5..c76b36895 100644
--- a/channel-transport/transport-nutils/requirements.txt
+++ b/channel-transport/transport-nutils/requirements.txt
@@ -1,6 +1,6 @@
-setuptools # required by nutils
+setuptools>=69.0.0 # required by nutils
nutils~=7.3
numpy >1, <2
# remeshing support will be released with preCICE version 3.2
pyprecice @ git+https://github.com/precice/python-bindings.git@develop
-setuptools
+setuptools>=69.0.0
diff --git a/channel-transport/transport-nutils/run.sh b/channel-transport/transport-nutils/run.sh
index c36a5bf49..1a01ed51f 100755
--- a/channel-transport/transport-nutils/run.sh
+++ b/channel-transport/transport-nutils/run.sh
@@ -4,11 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
python3 transport.py "$@"
diff --git a/elastic-tube-1d/.gitignore b/elastic-tube-1d/.gitignore
deleted file mode 100644
index 584556938..000000000
--- a/elastic-tube-1d/.gitignore
+++ /dev/null
@@ -1,11 +0,0 @@
-fluid-cpp/build/
-fluid-cpp/output/*.vtk
-solid-cpp/build/
-fluid-python/__pycache__/
-fluid-python/output/*.vtk
-solid-python/__pycache__/
-
-*.o
-*.log
-*.json
-*.pyc
diff --git a/elastic-tube-1d/fluid-fortran-module/.gitignore b/elastic-tube-1d/fluid-fortran-module/.gitignore
new file mode 100644
index 000000000..1066763d1
--- /dev/null
+++ b/elastic-tube-1d/fluid-fortran-module/.gitignore
@@ -0,0 +1 @@
+thirdparty/
\ No newline at end of file
diff --git a/elastic-tube-1d/fluid-fortran-module/CMakeLists.txt b/elastic-tube-1d/fluid-fortran-module/CMakeLists.txt
index 706fd822f..2db65502e 100644
--- a/elastic-tube-1d/fluid-fortran-module/CMakeLists.txt
+++ b/elastic-tube-1d/fluid-fortran-module/CMakeLists.txt
@@ -20,7 +20,7 @@ add_executable(FluidSolver
src/FluidComputeSolution.f90
src/utilities.f90
src/FluidSolver.f90
- src/precice.f90
+ thirdparty/precice.f90
)
target_link_libraries(FluidSolver PRIVATE precice::precice)
diff --git a/elastic-tube-1d/fluid-fortran-module/run.sh b/elastic-tube-1d/fluid-fortran-module/run.sh
index 0b6d315c7..a7e3326cb 100755
--- a/elastic-tube-1d/fluid-fortran-module/run.sh
+++ b/elastic-tube-1d/fluid-fortran-module/run.sh
@@ -4,9 +4,11 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -f src/precice.f90 ]; then
- echo "Fetching precice.f90 (Module for Fortran bindings of preCICE)..."
- curl -o src/precice.f90 https://raw.githubusercontent.com/precice/fortran-module/master/precice.f90
+if [ ! -f thirdparty/precice.f90 ]; then
+ # Get the preCICE Fortran module. Switch the branch with ./run.sh .
+ DEFAULT_BRANCH="main"
+ echo "Fetching precice.f90 from https://github.com/precice/fortran-module/tree/${1:-$DEFAULT_BRANCH}..."
+ curl --create-dirs -o thirdparty/precice.f90 "https://raw.githubusercontent.com/precice/fortran-module/${1:-$DEFAULT_BRANCH}/precice.f90"
fi
if [ ! -d build ]; then
diff --git a/elastic-tube-1d/fluid-fortran-module/src/FluidSolver.f90 b/elastic-tube-1d/fluid-fortran-module/src/FluidSolver.f90
index f2b4485f5..3087c09c7 100644
--- a/elastic-tube-1d/fluid-fortran-module/src/FluidSolver.f90
+++ b/elastic-tube-1d/fluid-fortran-module/src/FluidSolver.f90
@@ -101,7 +101,7 @@ program FluidSolver
vertexIDs(i) = i - 1
end do
- call precicef_set_vertices(meshName, chunkLength, grid, vertexIDs, len_trim(meshName))
+ call precicef_set_mesh_vertices(meshName, chunkLength, grid, vertexIDs, len_trim(meshName))
! Check if Initial Data is Required and Write if Necessary
call precicef_requires_initial_data(bool)
diff --git a/elastic-tube-1d/fluid-fortran/src/FluidSolver.f90 b/elastic-tube-1d/fluid-fortran/src/FluidSolver.f90
index 3df2f935b..5efb0bf2b 100644
--- a/elastic-tube-1d/fluid-fortran/src/FluidSolver.f90
+++ b/elastic-tube-1d/fluid-fortran/src/FluidSolver.f90
@@ -100,7 +100,7 @@ program FluidSolver
vertexIDs(i) = i - 1
end do
- call precicef_set_vertices(meshName, chunkLength, grid, vertexIDs)
+ call precicef_set_mesh_vertices(meshName, chunkLength, grid, vertexIDs)
! Check if Initial Data is Required and Write if Necessary
call precicef_requires_initial_data(bool)
diff --git a/elastic-tube-1d/fluid-python/requirements.txt b/elastic-tube-1d/fluid-python/requirements.txt
index 20ab73eb9..4bb3e60a1 100644
--- a/elastic-tube-1d/fluid-python/requirements.txt
+++ b/elastic-tube-1d/fluid-python/requirements.txt
@@ -1,3 +1,3 @@
-matplotlib
+matplotlib>=3.5,<4
numpy >1, <2
pyprecice~=3.0
\ No newline at end of file
diff --git a/elastic-tube-1d/fluid-python/run.sh b/elastic-tube-1d/fluid-python/run.sh
index 381bf0c1b..4cebb2088 100755
--- a/elastic-tube-1d/fluid-python/run.sh
+++ b/elastic-tube-1d/fluid-python/run.sh
@@ -4,11 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
python3 ./FluidSolver.py ../precice-config.xml
diff --git a/elastic-tube-1d/metadata.yaml b/elastic-tube-1d/metadata.yaml
index 79e66ab61..e8fcc30a8 100644
--- a/elastic-tube-1d/metadata.yaml
+++ b/elastic-tube-1d/metadata.yaml
@@ -10,32 +10,56 @@ cases:
fluid-cpp:
participant: Fluid
directory: ./fluid-cpp
- run: mkdir build && cmake -S . -B build && cmake --build build && ./run.sh
+ run: ./run.sh
component: bare
- solid-cpp:
- participant: Solid
- directory: ./solid-cpp
- run: mkdir build && cmake -S . -B build && cmake --build build && ./run.sh
+ fluid-fortran:
+ participant: Fluid
+ directory: ./fluid-fortran
+ run: ./run.sh
component: bare
-
+
+ fluid-fortran-module:
+ participant: Fluid
+ directory: ./fluid-fortran-module
+ run: ./run.sh develop
+ component: bare
+
fluid-python:
participant: Fluid
directory: ./fluid-python
run: ./run.sh
component: python-bindings
-
- solid-python:
- participant: Solid
- directory: ./solid-python
- run: ./run.sh
- component: python-bindings
-
+
fluid-rust:
participant: Fluid
directory: ./fluid-rust
run: ./run.sh
component: bare
+
+ solid-cpp:
+ participant: Solid
+ directory: ./solid-cpp
+ run: ./run.sh
+ component: bare
+
+ solid-fortran:
+ participant: Solid
+ directory: ./solid-fortran
+ run: ./run.sh
+ component: bare
+
+ solid-fortran-module:
+ participant: Solid
+ directory: ./solid-fortran-module
+ run: ./run.sh develop
+ component: bare
+
+ solid-python:
+ participant: Solid
+ directory: ./solid-python
+ run: ./run.sh
+ component: python-bindings
solid-rust:
participant: Solid
diff --git a/elastic-tube-1d/precice-config.xml b/elastic-tube-1d/precice-config.xml
index d99f72cbd..5bd79cba8 100644
--- a/elastic-tube-1d/precice-config.xml
+++ b/elastic-tube-1d/precice-config.xml
@@ -1,7 +1,10 @@
-
-
+
+
diff --git a/elastic-tube-1d/reference-results/fluid-cpp_solid-cpp.tar.gz b/elastic-tube-1d/reference-results/fluid-cpp_solid-cpp.tar.gz
index d5adab288..09b084538 100644
--- a/elastic-tube-1d/reference-results/fluid-cpp_solid-cpp.tar.gz
+++ b/elastic-tube-1d/reference-results/fluid-cpp_solid-cpp.tar.gz
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:329e96749e9f573cffe116405ef2e5c2dbc1c1fc1328c588ea6546d70a902428
-size 706930
+oid sha256:96e14acd91881112e38f7e4445329c565178353b62c1bebbc8a72a63d03cc0e6
+size 250333
diff --git a/elastic-tube-1d/reference-results/fluid-cpp_solid-python.tar.gz b/elastic-tube-1d/reference-results/fluid-cpp_solid-python.tar.gz
index b026f51ec..6131ee3d1 100644
--- a/elastic-tube-1d/reference-results/fluid-cpp_solid-python.tar.gz
+++ b/elastic-tube-1d/reference-results/fluid-cpp_solid-python.tar.gz
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:92f9751843f55dd2ffa4c82d86193eecf40aebb0987ccaf7b02f2263a156f14c
-size 707211
+oid sha256:6c79542944d1d623b8a39110e8534b7297a1f5fe62348c00e4e34279e23ae25b
+size 25969
diff --git a/elastic-tube-1d/reference-results/fluid-fortran-module_solid-fortran-module.tar.gz b/elastic-tube-1d/reference-results/fluid-fortran-module_solid-fortran-module.tar.gz
new file mode 100644
index 000000000..429320763
--- /dev/null
+++ b/elastic-tube-1d/reference-results/fluid-fortran-module_solid-fortran-module.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6cf76ce3df2836f842c3db9928ba3fe97af7e14c6244f45e5c672379481254af
+size 250849
diff --git a/elastic-tube-1d/reference-results/fluid-fortran_solid-fortran.tar.gz b/elastic-tube-1d/reference-results/fluid-fortran_solid-fortran.tar.gz
new file mode 100644
index 000000000..01e80c00e
--- /dev/null
+++ b/elastic-tube-1d/reference-results/fluid-fortran_solid-fortran.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:53809112177efdeec4c89e697aaf411c6203dbfb96414c8a1213219cff68c0a6
+size 250700
diff --git a/elastic-tube-1d/reference-results/fluid-python_solid-python.tar.gz b/elastic-tube-1d/reference-results/fluid-python_solid-python.tar.gz
index d752c1f9b..f35239055 100644
--- a/elastic-tube-1d/reference-results/fluid-python_solid-python.tar.gz
+++ b/elastic-tube-1d/reference-results/fluid-python_solid-python.tar.gz
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:ff7e3e50b59d6bc6398c75678181bc12cccc0e1397fdba901503e1f1897dec4a
-size 707288
+oid sha256:662da5d26698496aa97afea77df1c3cc928faa4432a96a893fc91decea12adfd
+size 250944
diff --git a/elastic-tube-1d/reference-results/reference_results.metadata b/elastic-tube-1d/reference-results/reference_results.metadata
index cf0fc5b06..aa78ae01d 100644
--- a/elastic-tube-1d/reference-results/reference_results.metadata
+++ b/elastic-tube-1d/reference-results/reference_results.metadata
@@ -11,38 +11,40 @@ We also include some information on the machine used to generate them
| name | time | sha256 |
|------|------|-------|
-| fluid-cpp_solid-cpp.tar.gz | 2026-05-11 07:45:27 | 329e96749e9f573cffe116405ef2e5c2dbc1c1fc1328c588ea6546d70a902428 |
-| fluid-cpp_solid-python.tar.gz | 2026-05-11 07:45:27 | 92f9751843f55dd2ffa4c82d86193eecf40aebb0987ccaf7b02f2263a156f14c |
-| fluid-python_solid-python.tar.gz | 2026-05-11 07:45:27 | ff7e3e50b59d6bc6398c75678181bc12cccc0e1397fdba901503e1f1897dec4a |
+| fluid-fortran-module_solid-fortran-module.tar.gz | 2026-05-30 12:38:08 | 6cf76ce3df2836f842c3db9928ba3fe97af7e14c6244f45e5c672379481254af |
+| fluid-cpp_solid-python.tar.gz | 2026-05-30 12:38:08 | 6c79542944d1d623b8a39110e8534b7297a1f5fe62348c00e4e34279e23ae25b |
+| fluid-fortran_solid-fortran.tar.gz | 2026-05-30 12:38:08 | 53809112177efdeec4c89e697aaf411c6203dbfb96414c8a1213219cff68c0a6 |
+| fluid-cpp_solid-cpp.tar.gz | 2026-05-30 12:38:08 | 96e14acd91881112e38f7e4445329c565178353b62c1bebbc8a72a63d03cc0e6 |
+| fluid-python_solid-python.tar.gz | 2026-05-30 12:38:08 | 662da5d26698496aa97afea77df1c3cc928faa4432a96a893fc91decea12adfd |
## List of arguments used to generate the files
| name | value |
|------|------|
-| PRECICE_REF | d199bb3 |
-| PRECICE_PRESET | production-audit |
-| OPENFOAM_EXECUTABLE | openfoam2312 |
-| OPENFOAM_ADAPTER_REF | v1.3.1 |
-| PYTHON_BINDINGS_REF | v3.2.0 |
-| FENICS_ADAPTER_REF | v2.2.0 |
-| TUTORIALS_REF | b18b3ef |
| PLATFORM | ubuntu_2404 |
| CALCULIX_VERSION | 2.20 |
-| CALCULIX_ADAPTER_REF | v2.20.1 |
-| SU2_VERSION | 7.5.1 |
-| SU2_ADAPTER_REF | 64d4aff |
-| DEALII_ADAPTER_REF | 02c5d18 |
| DUNE_VERSION | 2.9 |
| DUMUX_VERSION | 3.7 |
-| DUMUX_ADAPTER_REF | 0e914bb |
-| MICRO_MANAGER_REF | v0.8.0 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | f3b3bc2 |
+| PRECICE_PRESET | production-audit |
| PRECICE_UID | 1003 |
| PRECICE_GID | 1003 |
## Information about the machine
### uname -a
-Linux precice-tests 5.15.0-177-generic #187-Ubuntu SMP Sat Apr 11 22:54:33 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
### lscpu
diff --git a/elastic-tube-1d/solid-fortran-module/.gitignore b/elastic-tube-1d/solid-fortran-module/.gitignore
new file mode 100644
index 000000000..1066763d1
--- /dev/null
+++ b/elastic-tube-1d/solid-fortran-module/.gitignore
@@ -0,0 +1 @@
+thirdparty/
\ No newline at end of file
diff --git a/elastic-tube-1d/solid-fortran-module/CMakeLists.txt b/elastic-tube-1d/solid-fortran-module/CMakeLists.txt
index a1be8258f..2dd4005f7 100644
--- a/elastic-tube-1d/solid-fortran-module/CMakeLists.txt
+++ b/elastic-tube-1d/solid-fortran-module/CMakeLists.txt
@@ -18,7 +18,7 @@ find_package(precice 3 REQUIRED CONFIG)
add_executable(SolidSolver
src/SolidComputeSolution.f90
src/SolidSolver.f90
- src/precice.f90
+ thirdparty/precice.f90
)
target_link_libraries(SolidSolver PRIVATE precice::precice)
diff --git a/elastic-tube-1d/solid-fortran-module/run.sh b/elastic-tube-1d/solid-fortran-module/run.sh
index 337bd8c1f..4e9ca3dff 100755
--- a/elastic-tube-1d/solid-fortran-module/run.sh
+++ b/elastic-tube-1d/solid-fortran-module/run.sh
@@ -1,20 +1,20 @@
#!/usr/bin/env bash
set -e -u
-. ../../tools/log.sh || true
+. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1 || true
-if [ ! -f src/precice.f90 ]; then
- echo "Fetching precice.f90 (Module for Fortran bindings of preCICE)..."
- curl -o src/precice.f90 https://raw.githubusercontent.com/precice/fortran-module/master/precice.f90
+if [ ! -f thirdparty/precice.f90 ]; then
+ # Get the preCICE Fortran module. Switch the branch with ./run.sh .
+ DEFAULT_BRANCH="main"
+ echo "Fetching precice.f90 from https://github.com/precice/fortran-module/tree/${1:-$DEFAULT_BRANCH}..."
+ curl --create-dirs -o thirdparty/precice.f90 "https://raw.githubusercontent.com/precice/fortran-module/${1:-$DEFAULT_BRANCH}/precice.f90"
fi
if [ ! -d build ]; then
mkdir build
- cd build
- cmake ..
- cmake --build .
- cd ..
+ cmake -S . -B build
+ cmake --build build
fi
./build/SolidSolver ../precice-config.xml
diff --git a/elastic-tube-1d/solid-fortran-module/src/SolidSolver.f90 b/elastic-tube-1d/solid-fortran-module/src/SolidSolver.f90
index 86be2925f..a10174295 100644
--- a/elastic-tube-1d/solid-fortran-module/src/SolidSolver.f90
+++ b/elastic-tube-1d/solid-fortran-module/src/SolidSolver.f90
@@ -63,7 +63,7 @@ program SolidSolver
vertexIDs(i) = i - 1 ! 0-based indexing here
end do
- call precicef_set_vertices(meshName, chunkLength, grid, vertexIDs, &
+ call precicef_set_mesh_vertices(meshName, chunkLength, grid, vertexIDs, &
len_trim(meshName))
! Check if initial data is required and write if necessary
diff --git a/elastic-tube-1d/solid-fortran/src/SolidSolver.f90 b/elastic-tube-1d/solid-fortran/src/SolidSolver.f90
index 9de1b1d63..bbd5e4716 100644
--- a/elastic-tube-1d/solid-fortran/src/SolidSolver.f90
+++ b/elastic-tube-1d/solid-fortran/src/SolidSolver.f90
@@ -59,7 +59,7 @@ program SolidSolver
vertexIDs(i) = i - 1 ! 0-based indexing here
end do
- call precicef_set_vertices(meshName, chunkLength, grid, vertexIDs)
+ call precicef_set_mesh_vertices(meshName, chunkLength, grid, vertexIDs)
! Check if initial data is required and write if necessary
call precicef_requires_initial_data(bool)
diff --git a/elastic-tube-1d/solid-python/run.sh b/elastic-tube-1d/solid-python/run.sh
index 60fba521e..73674234d 100755
--- a/elastic-tube-1d/solid-python/run.sh
+++ b/elastic-tube-1d/solid-python/run.sh
@@ -4,11 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
python3 ./SolidSolver.py ../precice-config.xml
diff --git a/elastic-tube-3d/README.md b/elastic-tube-3d/README.md
index 4adac850a..3d450b48d 100644
--- a/elastic-tube-3d/README.md
+++ b/elastic-tube-3d/README.md
@@ -31,7 +31,7 @@ Solid participant:
* CalculiX. For more information, have a look at the [CalculiX adapter documentation](https://precice.org/adapter-calculix-overview.html).
-* FEniCS. The structural model is currently limited to linear elasticity. Currently 3D functionality is experimental in the FEniCS adapter and more details can be found [here](https://github.com/precice/fenics-adapter/pull/133) For more information, have a look at the [FeniCS adapter documentation](https://precice.org/adapter-fenics.html).
+* FEniCS. The structural model is currently limited to linear elasticity. Currently 3D functionality is experimental in the FEniCS adapter and more details can be found [in this discussion](https://github.com/precice/fenics-adapter/pull/133). For more information, have a look at the [FeniCS adapter documentation](https://precice.org/adapter-fenics.html).
## Running the simulation
diff --git a/elastic-tube-3d/metadata.yaml b/elastic-tube-3d/metadata.yaml
index 04b45db3c..438888d8b 100644
--- a/elastic-tube-3d/metadata.yaml
+++ b/elastic-tube-3d/metadata.yaml
@@ -10,7 +10,7 @@ cases:
fluid-openfoam:
participant: Fluid
directory: ./fluid-openfoam
- run: ./run.sh
+ run: ./run.sh -parallel
component: openfoam-adapter
solid-calculix:
diff --git a/elastic-tube-3d/reference-results/fluid-openfoam_solid-calculix.tar.gz b/elastic-tube-3d/reference-results/fluid-openfoam_solid-calculix.tar.gz
new file mode 100644
index 000000000..d409a8bf1
--- /dev/null
+++ b/elastic-tube-3d/reference-results/fluid-openfoam_solid-calculix.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:cb1fc445a9c31b7065b172c8fb35b05796367d7b350c0c648df0b4293a5c30bb
+size 1100768
diff --git a/elastic-tube-3d/reference-results/fluid-openfoam_solid-fenics.tar.gz b/elastic-tube-3d/reference-results/fluid-openfoam_solid-fenics.tar.gz
new file mode 100644
index 000000000..2cb32d19b
--- /dev/null
+++ b/elastic-tube-3d/reference-results/fluid-openfoam_solid-fenics.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:1ac3c623f4d831d8df501e095bc66d14968cde9f80dbb237eb46642c269808ad
+size 461609
diff --git a/elastic-tube-3d/reference-results/reference_results.metadata b/elastic-tube-3d/reference-results/reference_results.metadata
new file mode 100644
index 000000000..caec30c27
--- /dev/null
+++ b/elastic-tube-3d/reference-results/reference_results.metadata
@@ -0,0 +1,72 @@
+
+
+# Reference Results
+
+This file contains an overview of the results over the reference results as well as the arguments used to generate them.
+We also include some information on the machine used to generate them
+
+## List of files
+
+| name | time | sha256 |
+|------|------|-------|
+| fluid-openfoam_solid-fenics.tar.gz | 2026-05-28 11:46:06 | 1ac3c623f4d831d8df501e095bc66d14968cde9f80dbb237eb46642c269808ad |
+| fluid-openfoam_solid-calculix.tar.gz | 2026-05-28 11:46:06 | cb1fc445a9c31b7065b172c8fb35b05796367d7b350c0c648df0b4293a5c30bb |
+
+## List of arguments used to generate the files
+
+| name | value |
+|------|------|
+| PLATFORM | ubuntu_2404 |
+| CALCULIX_VERSION | 2.20 |
+| DUNE_VERSION | 2.9 |
+| DUMUX_VERSION | 3.7 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | 9cb7068 |
+| PRECICE_PRESET | production-audit |
+| PRECICE_UID | 1003 |
+| PRECICE_GID | 1003 |
+## Information about the machine
+
+### uname -a
+
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+
+
+### lscpu
+
+Architecture: x86_64
+CPU op-mode(s): 32-bit, 64-bit
+Address sizes: 45 bits physical, 48 bits virtual
+Byte Order: Little Endian
+CPU(s): 4
+On-line CPU(s) list: 0-3
+Vendor ID: GenuineIntel
+Model name: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz
+CPU family: 6
+Model: 85
+Thread(s) per core: 1
+Core(s) per socket: 1
+Socket(s): 4
+Stepping: 4
+BogoMIPS: 4199.99
+Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat pku ospke md_clear flush_l1d arch_capabilities
+Hypervisor vendor: VMware
+Virtualization type: full
+L1d cache: 128 KiB (4 instances)
+L1i cache: 128 KiB (4 instances)
+L2 cache: 4 MiB (4 instances)
+L3 cache: 88 MiB (4 instances)
+NUMA node(s): 1
+NUMA node0 CPU(s): 0-3
diff --git a/elastic-tube-3d/solid-fenics/run.sh b/elastic-tube-3d/solid-fenics/run.sh
index a06dd46bb..fb2c0a0e9 100755
--- a/elastic-tube-3d/solid-fenics/run.sh
+++ b/elastic-tube-3d/solid-fenics/run.sh
@@ -4,11 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv --system-site-package .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv --system-site-packages .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
python3 solid.py
diff --git a/flow-around-controlled-moving-cylinder/.gitignore b/flow-around-controlled-moving-cylinder/.gitignore
deleted file mode 100644
index 043bb5f18..000000000
--- a/flow-around-controlled-moving-cylinder/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-controller-fmi/PIDcontroller.fmu
-controller-fmi/output/
-fluid-openfoam/0/ # Since we start from 0.orig
diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/requirements.txt b/flow-around-controlled-moving-cylinder/controller-fmi/requirements.txt
index 10f7ea9df..09a2e2195 100644
--- a/flow-around-controlled-moving-cylinder/controller-fmi/requirements.txt
+++ b/flow-around-controlled-moving-cylinder/controller-fmi/requirements.txt
@@ -1 +1 @@
-fmiprecice
\ No newline at end of file
+fmiprecice~=0.2
diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/run.sh b/flow-around-controlled-moving-cylinder/controller-fmi/run.sh
index 57be1215c..4ec90931e 100755
--- a/flow-around-controlled-moving-cylinder/controller-fmi/run.sh
+++ b/flow-around-controlled-moving-cylinder/controller-fmi/run.sh
@@ -15,11 +15,14 @@ if [ ! -f PIDcontroller.fmu ]; then
cd ../../
fi
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
fmiprecice ./fmi-settings.json ./precice-settings.json
diff --git a/flow-around-controlled-moving-cylinder/fluid-openfoam/.gitignore b/flow-around-controlled-moving-cylinder/fluid-openfoam/.gitignore
new file mode 100644
index 000000000..9a342fb3d
--- /dev/null
+++ b/flow-around-controlled-moving-cylinder/fluid-openfoam/.gitignore
@@ -0,0 +1,2 @@
+# Pre-processing 0.orig
+0/
diff --git a/flow-around-controlled-moving-cylinder/metadata.yaml b/flow-around-controlled-moving-cylinder/metadata.yaml
new file mode 100644
index 000000000..1b95b1469
--- /dev/null
+++ b/flow-around-controlled-moving-cylinder/metadata.yaml
@@ -0,0 +1,28 @@
+name: Flow around a controlled moving cylinder
+path: flow-around-controlled-moving-cylinder
+url: https://precice.org/tutorials-flow-around-controlled-moving-cylinder.html
+
+participants:
+ - Controller
+ - Fluid
+ - Solid
+
+cases:
+ controller-fmi:
+ participant: Controller
+ directory: ./controller-fmi
+ run: ./run.sh
+ component: python-bindings
+
+ fluid-openfoam:
+ participant: Fluid
+ directory: ./fluid-openfoam
+ run: ./run.sh
+ component: openfoam-adapter
+
+ solid-python:
+ participant: Solid
+ directory: ./solid-python
+ run: ./run.sh
+ component: python-bindings
+
\ No newline at end of file
diff --git a/flow-around-controlled-moving-cylinder/reference-results/controller-fmi_fluid-openfoam_solid-python.tar.gz b/flow-around-controlled-moving-cylinder/reference-results/controller-fmi_fluid-openfoam_solid-python.tar.gz
new file mode 100644
index 000000000..11545f75b
--- /dev/null
+++ b/flow-around-controlled-moving-cylinder/reference-results/controller-fmi_fluid-openfoam_solid-python.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:8e948b0f82d011cf61a34c37f5ea7ae0f93c5fe67b0ab3ce49d49f7ba05e6fc2
+size 61863
diff --git a/flow-around-controlled-moving-cylinder/reference-results/reference_results.metadata b/flow-around-controlled-moving-cylinder/reference-results/reference_results.metadata
new file mode 100644
index 000000000..e98228b1d
--- /dev/null
+++ b/flow-around-controlled-moving-cylinder/reference-results/reference_results.metadata
@@ -0,0 +1,71 @@
+
+
+# Reference Results
+
+This file contains an overview of the results over the reference results as well as the arguments used to generate them.
+We also include some information on the machine used to generate them
+
+## List of files
+
+| name | time | sha256 |
+|------|------|-------|
+| controller-fmi_fluid-openfoam_solid-python.tar.gz | 2026-05-30 15:34:58 | 8e948b0f82d011cf61a34c37f5ea7ae0f93c5fe67b0ab3ce49d49f7ba05e6fc2 |
+
+## List of arguments used to generate the files
+
+| name | value |
+|------|------|
+| PLATFORM | ubuntu_2404 |
+| CALCULIX_VERSION | 2.20 |
+| DUNE_VERSION | 2.9 |
+| DUMUX_VERSION | 3.7 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | more-tests |
+| PRECICE_PRESET | production-audit |
+| PRECICE_UID | 1003 |
+| PRECICE_GID | 1003 |
+## Information about the machine
+
+### uname -a
+
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+
+
+### lscpu
+
+Architecture: x86_64
+CPU op-mode(s): 32-bit, 64-bit
+Address sizes: 45 bits physical, 48 bits virtual
+Byte Order: Little Endian
+CPU(s): 4
+On-line CPU(s) list: 0-3
+Vendor ID: GenuineIntel
+Model name: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz
+CPU family: 6
+Model: 85
+Thread(s) per core: 1
+Core(s) per socket: 1
+Socket(s): 4
+Stepping: 4
+BogoMIPS: 4199.99
+Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat pku ospke md_clear flush_l1d arch_capabilities
+Hypervisor vendor: VMware
+Virtualization type: full
+L1d cache: 128 KiB (4 instances)
+L1i cache: 128 KiB (4 instances)
+L2 cache: 4 MiB (4 instances)
+L3 cache: 88 MiB (4 instances)
+NUMA node(s): 1
+NUMA node0 CPU(s): 0-3
diff --git a/flow-around-controlled-moving-cylinder/solid-python/run.sh b/flow-around-controlled-moving-cylinder/solid-python/run.sh
index 0b6c1f894..6f77463d6 100755
--- a/flow-around-controlled-moving-cylinder/solid-python/run.sh
+++ b/flow-around-controlled-moving-cylinder/solid-python/run.sh
@@ -4,11 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
python3 solid.py ../precice-config.xml
diff --git a/flow-over-heated-plate-nearest-projection/metadata.yaml b/flow-over-heated-plate-nearest-projection/metadata.yaml
index dbd1936c8..046528f09 100644
--- a/flow-over-heated-plate-nearest-projection/metadata.yaml
+++ b/flow-over-heated-plate-nearest-projection/metadata.yaml
@@ -10,11 +10,11 @@ cases:
fluid-openfoam:
participant: Fluid
directory: ./fluid-openfoam
- run: ./run.sh
+ run: ./run.sh -parallel
component: openfoam-adapter
solid-openfoam:
participant: Solid
directory: ./solid-openfoam
- run: ./run.sh
+ run: ./run.sh -parallel
component: openfoam-adapter
diff --git a/flow-over-heated-plate-nearest-projection/reference-results/fluid-openfoam_solid-openfoam.tar.gz b/flow-over-heated-plate-nearest-projection/reference-results/fluid-openfoam_solid-openfoam.tar.gz
index 4a7f74021..81b93176c 100644
--- a/flow-over-heated-plate-nearest-projection/reference-results/fluid-openfoam_solid-openfoam.tar.gz
+++ b/flow-over-heated-plate-nearest-projection/reference-results/fluid-openfoam_solid-openfoam.tar.gz
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:1a61f981eb713f32f0b47435512857e346e5a9aac01794c815dc2531b2ca32e6
-size 1831520
+oid sha256:3e15f7e09b131d5939d6d87e9c617603752aeb39110c595db6535b7a2e9fc6a4
+size 58968
diff --git a/flow-over-heated-plate-nearest-projection/reference-results/reference_results.metadata b/flow-over-heated-plate-nearest-projection/reference-results/reference_results.metadata
index 7a1a921c8..638d36e88 100644
--- a/flow-over-heated-plate-nearest-projection/reference-results/reference_results.metadata
+++ b/flow-over-heated-plate-nearest-projection/reference-results/reference_results.metadata
@@ -11,36 +11,36 @@ We also include some information on the machine used to generate them
| name | time | sha256 |
|------|------|-------|
-| fluid-openfoam_solid-openfoam.tar.gz | 2026-05-11 07:45:27 | 1a61f981eb713f32f0b47435512857e346e5a9aac01794c815dc2531b2ca32e6 |
+| fluid-openfoam_solid-openfoam.tar.gz | 2026-05-28 11:46:06 | 3e15f7e09b131d5939d6d87e9c617603752aeb39110c595db6535b7a2e9fc6a4 |
## List of arguments used to generate the files
| name | value |
|------|------|
-| PRECICE_REF | d199bb3 |
-| PRECICE_PRESET | production-audit |
-| OPENFOAM_EXECUTABLE | openfoam2312 |
-| OPENFOAM_ADAPTER_REF | v1.3.1 |
-| PYTHON_BINDINGS_REF | v3.2.0 |
-| FENICS_ADAPTER_REF | v2.2.0 |
-| TUTORIALS_REF | b18b3ef |
| PLATFORM | ubuntu_2404 |
| CALCULIX_VERSION | 2.20 |
-| CALCULIX_ADAPTER_REF | v2.20.1 |
-| SU2_VERSION | 7.5.1 |
-| SU2_ADAPTER_REF | 64d4aff |
-| DEALII_ADAPTER_REF | 02c5d18 |
| DUNE_VERSION | 2.9 |
| DUMUX_VERSION | 3.7 |
-| DUMUX_ADAPTER_REF | 0e914bb |
-| MICRO_MANAGER_REF | v0.8.0 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | 9cb7068 |
+| PRECICE_PRESET | production-audit |
| PRECICE_UID | 1003 |
| PRECICE_GID | 1003 |
## Information about the machine
### uname -a
-Linux precice-tests 5.15.0-177-generic #187-Ubuntu SMP Sat Apr 11 22:54:33 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
### lscpu
diff --git a/flow-over-heated-plate-partitioned-flow/README.md b/flow-over-heated-plate-partitioned-flow/README.md
index 7fd84fbfe..2e7b4f47e 100644
--- a/flow-over-heated-plate-partitioned-flow/README.md
+++ b/flow-over-heated-plate-partitioned-flow/README.md
@@ -14,7 +14,7 @@ Get the [case files of this tutorial](https://github.com/precice/tutorials/tree/
The setup for this tutorial is similar to the [flow over a heated plate](https://precice.org/tutorials-flow-over-heated-plate.html). In this case we additionally partition the OpenFOAM fluid to create a three-way coupling using CHT (conjugate heat transfer) and FF (fluid-fluid coupling).
The test case is two-dimensional and uses a serial-implicit coupling with Quasi-Newton acceleration for the fluid-fluid coupling. The CHT coupling between the solid and the fluid2 participant is changed to serial-explicit because it does not make sense numerically to have multiple serial-implicit schemes.
-Note that it is usually recommended using the fully implicit parallel `coupling-scheme:multi` with more than two participants. (learn more about this [here](https://precice.org/configuration-coupling-multi.html)). However, in this basic example, it is sufficient to do the CHT coupling explicitly.
+Note that it is usually recommended using the fully implicit parallel `coupling-scheme:multi` with more than two participants. (see [multi-coupling configuration](https://precice.org/configuration-coupling-multi.html)). However, in this basic example, it is sufficient to do the CHT coupling explicitly.
The flow partitioning is done with the fluid-fluid module of the [preCICE OpenFOAM adapter](https://precice.org/adapter-openfoam-overview.html). Because we use buoyantPimpleFoam we have to tell the adapter that the coupled pressure has the name `p_rgh`. The temperature is coupled at the fluid-solid interface by exchanging *Temperature* and *Heat-Flux*, at the fluid-fluid interface it is *FlowTemperature* and *FlowTemperatureGradient*. Note the difference in naming: *Temperature* is used for conjugate heat transfer and *FlowTemperature* for fluid-fluid coupling.
diff --git a/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/system/controlDict b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/system/controlDict
index 592cdb75a..de0414779 100644
--- a/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/system/controlDict
+++ b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/system/controlDict
@@ -20,7 +20,7 @@ deltaT 0.01;
writeControl runTime;
-writeInterval 0.2;
+writeInterval 0.1;
purgeWrite 0;
diff --git a/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/system/controlDict b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/system/controlDict
index 592cdb75a..de0414779 100644
--- a/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/system/controlDict
+++ b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/system/controlDict
@@ -20,7 +20,7 @@ deltaT 0.01;
writeControl runTime;
-writeInterval 0.2;
+writeInterval 0.1;
purgeWrite 0;
diff --git a/flow-over-heated-plate-partitioned-flow/metadata.yaml b/flow-over-heated-plate-partitioned-flow/metadata.yaml
new file mode 100644
index 000000000..ddd86c96a
--- /dev/null
+++ b/flow-over-heated-plate-partitioned-flow/metadata.yaml
@@ -0,0 +1,30 @@
+name: Flow over heated plate partitioned flow
+path: flow-over-heated-plate-partitioned-flow # relative to git repo
+url: https://precice.org/tutorials-flow-over-heated-plate-partitioned-flow.html
+
+participants:
+ - Fluid1
+ - Fluid2
+ - Solid
+
+cases:
+ fluid1-openfoam:
+ participant: Fluid1
+ directory: ./fluid1-openfoam
+ run: ./run.sh
+ component: openfoam-adapter
+
+ fluid2-openfoam:
+ participant: Fluid2
+ directory: ./fluid2-openfoam
+ run: ./run.sh
+ component: openfoam-adapter
+
+ solid-openfoam:
+ participant: Solid
+ directory: ./solid-openfoam
+ run: ./run.sh
+ component: openfoam-adapter
+
+
+
diff --git a/flow-over-heated-plate-partitioned-flow/reference-results/fluid1-openfoam_fluid2-openfoam_solid-openfoam.tar.gz b/flow-over-heated-plate-partitioned-flow/reference-results/fluid1-openfoam_fluid2-openfoam_solid-openfoam.tar.gz
new file mode 100644
index 000000000..d3cb5e476
--- /dev/null
+++ b/flow-over-heated-plate-partitioned-flow/reference-results/fluid1-openfoam_fluid2-openfoam_solid-openfoam.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ab86d97f4c78282972e1ff9c4c5603a762e2e0d53442b067e408beabcc7b563a
+size 48427
diff --git a/flow-over-heated-plate-partitioned-flow/reference-results/reference_results.metadata b/flow-over-heated-plate-partitioned-flow/reference-results/reference_results.metadata
new file mode 100644
index 000000000..5200a89d8
--- /dev/null
+++ b/flow-over-heated-plate-partitioned-flow/reference-results/reference_results.metadata
@@ -0,0 +1,71 @@
+
+
+# Reference Results
+
+This file contains an overview of the results over the reference results as well as the arguments used to generate them.
+We also include some information on the machine used to generate them
+
+## List of files
+
+| name | time | sha256 |
+|------|------|-------|
+| fluid1-openfoam_fluid2-openfoam_solid-openfoam.tar.gz | 2026-05-30 22:01:39 | ab86d97f4c78282972e1ff9c4c5603a762e2e0d53442b067e408beabcc7b563a |
+
+## List of arguments used to generate the files
+
+| name | value |
+|------|------|
+| PLATFORM | ubuntu_2404 |
+| CALCULIX_VERSION | 2.20 |
+| DUNE_VERSION | 2.9 |
+| DUMUX_VERSION | 3.7 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | more-tests |
+| PRECICE_PRESET | production-audit |
+| PRECICE_UID | 1003 |
+| PRECICE_GID | 1003 |
+## Information about the machine
+
+### uname -a
+
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+
+
+### lscpu
+
+Architecture: x86_64
+CPU op-mode(s): 32-bit, 64-bit
+Address sizes: 45 bits physical, 48 bits virtual
+Byte Order: Little Endian
+CPU(s): 4
+On-line CPU(s) list: 0-3
+Vendor ID: GenuineIntel
+Model name: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz
+CPU family: 6
+Model: 85
+Thread(s) per core: 1
+Core(s) per socket: 1
+Socket(s): 4
+Stepping: 4
+BogoMIPS: 4199.99
+Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat pku ospke md_clear flush_l1d arch_capabilities
+Hypervisor vendor: VMware
+Virtualization type: full
+L1d cache: 128 KiB (4 instances)
+L1i cache: 128 KiB (4 instances)
+L2 cache: 4 MiB (4 instances)
+L3 cache: 88 MiB (4 instances)
+NUMA node(s): 1
+NUMA node0 CPU(s): 0-3
diff --git a/flow-over-heated-plate-partitioned-flow/solid-openfoam/system/controlDict b/flow-over-heated-plate-partitioned-flow/solid-openfoam/system/controlDict
index 7cb0aee74..29dd66867 100644
--- a/flow-over-heated-plate-partitioned-flow/solid-openfoam/system/controlDict
+++ b/flow-over-heated-plate-partitioned-flow/solid-openfoam/system/controlDict
@@ -21,7 +21,7 @@ deltaT 0.01;
writeControl runTime;
-writeInterval 0.2;
+writeInterval 0.1;
purgeWrite 0;
diff --git a/flow-over-heated-plate-steady-state/metadata.yaml b/flow-over-heated-plate-steady-state/metadata.yaml
new file mode 100644
index 000000000..1bc65d444
--- /dev/null
+++ b/flow-over-heated-plate-steady-state/metadata.yaml
@@ -0,0 +1,20 @@
+name: Flow over heated plate steady state
+path: flow-over-heated-plate-steady-state # relative to git repo
+url: https://precice.org/tutorials-flow-over-heated-plate-steady-state.html
+
+participants:
+ - Fluid
+ - Solid
+
+cases:
+ fluid-openfoam:
+ participant: Fluid
+ directory: ./fluid-openfoam
+ run: ./run.sh
+ component: openfoam-adapter
+
+ # solid-codeaster:
+ # participant: Solid
+ # directory: ./solid-codeaster
+ # run: ./run.sh
+ # component: codeaster-adapter
diff --git a/flow-over-heated-plate-two-meshes/metadata.yaml b/flow-over-heated-plate-two-meshes/metadata.yaml
new file mode 100644
index 000000000..c457cca11
--- /dev/null
+++ b/flow-over-heated-plate-two-meshes/metadata.yaml
@@ -0,0 +1,20 @@
+name: Flow over heated plate with two meshes
+path: flow-over-heated-plate-two-meshes # relative to git repo
+url: https://precice.org/tutorials-flow-over-heated-plate-two-meshes.html
+
+participants:
+ - Fluid
+ - Solid
+
+cases:
+ fluid-openfoam:
+ participant: Fluid
+ directory: ./fluid-openfoam
+ run: ./run.sh -parallel
+ component: openfoam-adapter
+
+ solid-calculix:
+ participant: Solid
+ directory: ./solid-calculix
+ run: ./run.sh
+ component: calculix-adapter
diff --git a/flow-over-heated-plate-two-meshes/reference-results/fluid-openfoam_solid-openfoam.tar.gz b/flow-over-heated-plate-two-meshes/reference-results/fluid-openfoam_solid-openfoam.tar.gz
new file mode 100644
index 000000000..adfa95dfd
--- /dev/null
+++ b/flow-over-heated-plate-two-meshes/reference-results/fluid-openfoam_solid-openfoam.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:19a5abd5df4ebdc556279600d6dfa31734f9ea3d7f13f51aec5e0526f638c3f9
+size 40717
diff --git a/flow-over-heated-plate-two-meshes/reference-results/reference_results.metadata b/flow-over-heated-plate-two-meshes/reference-results/reference_results.metadata
new file mode 100644
index 000000000..748d536bc
--- /dev/null
+++ b/flow-over-heated-plate-two-meshes/reference-results/reference_results.metadata
@@ -0,0 +1,71 @@
+
+
+# Reference Results
+
+This file contains an overview of the results over the reference results as well as the arguments used to generate them.
+We also include some information on the machine used to generate them
+
+## List of files
+
+| name | time | sha256 |
+|------|------|-------|
+| fluid-openfoam_solid-openfoam.tar.gz | 2026-05-28 11:46:06 | 19a5abd5df4ebdc556279600d6dfa31734f9ea3d7f13f51aec5e0526f638c3f9 |
+
+## List of arguments used to generate the files
+
+| name | value |
+|------|------|
+| PLATFORM | ubuntu_2404 |
+| CALCULIX_VERSION | 2.20 |
+| DUNE_VERSION | 2.9 |
+| DUMUX_VERSION | 3.7 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | 9cb7068 |
+| PRECICE_PRESET | production-audit |
+| PRECICE_UID | 1003 |
+| PRECICE_GID | 1003 |
+## Information about the machine
+
+### uname -a
+
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+
+
+### lscpu
+
+Architecture: x86_64
+CPU op-mode(s): 32-bit, 64-bit
+Address sizes: 45 bits physical, 48 bits virtual
+Byte Order: Little Endian
+CPU(s): 4
+On-line CPU(s) list: 0-3
+Vendor ID: GenuineIntel
+Model name: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz
+CPU family: 6
+Model: 85
+Thread(s) per core: 1
+Core(s) per socket: 1
+Socket(s): 4
+Stepping: 4
+BogoMIPS: 4199.99
+Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat pku ospke md_clear flush_l1d arch_capabilities
+Hypervisor vendor: VMware
+Virtualization type: full
+L1d cache: 128 KiB (4 instances)
+L1i cache: 128 KiB (4 instances)
+L2 cache: 4 MiB (4 instances)
+L3 cache: 88 MiB (4 instances)
+NUMA node(s): 1
+NUMA node0 CPU(s): 0-3
diff --git a/flow-over-heated-plate/fluid-su2/run.sh b/flow-over-heated-plate/fluid-su2/run.sh
index db3ab8b76..8b276b60b 100755
--- a/flow-over-heated-plate/fluid-su2/run.sh
+++ b/flow-over-heated-plate/fluid-su2/run.sh
@@ -4,11 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv --system-site-package .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv --system-site-packages .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
SU2_preCICE_CHT.py -f laminar_config_unsteady.cfg -r --parallel
diff --git a/flow-over-heated-plate/metadata.yaml b/flow-over-heated-plate/metadata.yaml
index 0fea0d842..ec86ec951 100644
--- a/flow-over-heated-plate/metadata.yaml
+++ b/flow-over-heated-plate/metadata.yaml
@@ -10,15 +10,33 @@ cases:
fluid-openfoam:
participant: Fluid
directory: ./fluid-openfoam
- run: ./run.sh
+ run: ./run.sh
component: openfoam-adapter
+ fluid-su2:
+ participant: Fluid
+ directory: ./fluid-su2
+ run: ./run.sh
+ component: su2-adapter
+
+ # solid-dunefem:
+ # partitipant: Solid
+ # directory: ./solid-dunefem
+ # run: ./run.sh
+ # component: ?
+
solid-fenics:
participant: Solid
directory: ./solid-fenics
run: ./run.sh
component: fenics-adapter
-
+
+ solid-fenicsx:
+ participant: Solid
+ directory: ./solid-fenicsx
+ run: ./run.sh
+ component: fenicsx-adapter
+
solid-nutils:
participant: Solid
directory: ./solid-nutils
@@ -28,7 +46,7 @@ cases:
solid-openfoam:
participant: Solid
directory: ./solid-openfoam
- run: ./run.sh
+ run: ./run.sh
component: openfoam-adapter
diff --git a/flow-over-heated-plate/reference-results/fluid-openfoam_solid-fenics.tar.gz b/flow-over-heated-plate/reference-results/fluid-openfoam_solid-fenics.tar.gz
index 2f0da01fe..24e5c7bb3 100644
--- a/flow-over-heated-plate/reference-results/fluid-openfoam_solid-fenics.tar.gz
+++ b/flow-over-heated-plate/reference-results/fluid-openfoam_solid-fenics.tar.gz
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:059d338dd1e93b3661b052665fa297a55668e7e81d385d409b12dcbbe0ac74ed
-size 771178
+oid sha256:38a2d7a489dc943abd52a9565e92ca43a747490654929629231ce856906e4723
+size 214130
diff --git a/flow-over-heated-plate/reference-results/fluid-openfoam_solid-fenicsx.tar.gz b/flow-over-heated-plate/reference-results/fluid-openfoam_solid-fenicsx.tar.gz
new file mode 100644
index 000000000..98780963b
--- /dev/null
+++ b/flow-over-heated-plate/reference-results/fluid-openfoam_solid-fenicsx.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b31adcb4938e92dd05418425329281f48a86575792fc5063a65f4ef03be058ae
+size 1128130
diff --git a/flow-over-heated-plate/reference-results/fluid-openfoam_solid-nutils.tar.gz b/flow-over-heated-plate/reference-results/fluid-openfoam_solid-nutils.tar.gz
index c8484c169..4486f2cc4 100644
--- a/flow-over-heated-plate/reference-results/fluid-openfoam_solid-nutils.tar.gz
+++ b/flow-over-heated-plate/reference-results/fluid-openfoam_solid-nutils.tar.gz
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:96d2748fcc27be2b8977b30192965ae5a736c679e3a2f26c2f6713348c2bc2f4
-size 532749
+oid sha256:e5c5243767d2b24c473a985e239152c72dcf040f49bc02c99f1175a0e7db1835
+size 6986
diff --git a/flow-over-heated-plate/reference-results/fluid-openfoam_solid-openfoam.tar.gz b/flow-over-heated-plate/reference-results/fluid-openfoam_solid-openfoam.tar.gz
index 9d84f0178..e9975cd76 100644
--- a/flow-over-heated-plate/reference-results/fluid-openfoam_solid-openfoam.tar.gz
+++ b/flow-over-heated-plate/reference-results/fluid-openfoam_solid-openfoam.tar.gz
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:758a2fb73703b7a693a8b2b2994dab0ff52e89b0b1ce25c8389571f3397cce15
-size 497675
+oid sha256:7a92099a21a3043486453f0ceb1700ce79febad10e6e7ca6852435f31f5a9f7e
+size 136311
diff --git a/flow-over-heated-plate/reference-results/fluid-su2_solid-openfoam.tar.gz b/flow-over-heated-plate/reference-results/fluid-su2_solid-openfoam.tar.gz
new file mode 100644
index 000000000..01ddc9a17
--- /dev/null
+++ b/flow-over-heated-plate/reference-results/fluid-su2_solid-openfoam.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:9f09992b4c0a472dc1a978d5187c3e9c2335d298c93a79081fd30abbb941bfa8
+size 10704
diff --git a/flow-over-heated-plate/reference-results/reference_results.metadata b/flow-over-heated-plate/reference-results/reference_results.metadata
index bff70c8d8..2d90de3ff 100644
--- a/flow-over-heated-plate/reference-results/reference_results.metadata
+++ b/flow-over-heated-plate/reference-results/reference_results.metadata
@@ -11,38 +11,37 @@ We also include some information on the machine used to generate them
| name | time | sha256 |
|------|------|-------|
-| fluid-openfoam_solid-openfoam.tar.gz | 2026-05-11 07:45:27 | 758a2fb73703b7a693a8b2b2994dab0ff52e89b0b1ce25c8389571f3397cce15 |
-| fluid-openfoam_solid-fenics.tar.gz | 2026-05-11 07:45:27 | 059d338dd1e93b3661b052665fa297a55668e7e81d385d409b12dcbbe0ac74ed |
-| fluid-openfoam_solid-nutils.tar.gz | 2026-05-11 07:45:27 | 96d2748fcc27be2b8977b30192965ae5a736c679e3a2f26c2f6713348c2bc2f4 |
+| fluid-openfoam_solid-fenicsx.tar.gz | 2026-06-12 17:50:05 | b31adcb4938e92dd05418425329281f48a86575792fc5063a65f4ef03be058ae |
## List of arguments used to generate the files
| name | value |
|------|------|
-| PRECICE_REF | d199bb3 |
-| PRECICE_PRESET | production-audit |
-| OPENFOAM_EXECUTABLE | openfoam2312 |
-| OPENFOAM_ADAPTER_REF | v1.3.1 |
-| PYTHON_BINDINGS_REF | v3.2.0 |
-| FENICS_ADAPTER_REF | v2.2.0 |
-| TUTORIALS_REF | b18b3ef |
| PLATFORM | ubuntu_2404 |
| CALCULIX_VERSION | 2.20 |
-| CALCULIX_ADAPTER_REF | v2.20.1 |
-| SU2_VERSION | 7.5.1 |
-| SU2_ADAPTER_REF | 64d4aff |
-| DEALII_ADAPTER_REF | 02c5d18 |
| DUNE_VERSION | 2.9 |
| DUMUX_VERSION | 3.7 |
-| DUMUX_ADAPTER_REF | 0e914bb |
-| MICRO_MANAGER_REF | v0.8.0 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| FENICSX_ADAPTER_REF | v1.0.1 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | c1c5b4a3b044b5401d06f933204ff41e3252cedc |
+| PRECICE_PRESET | production-audit |
| PRECICE_UID | 1003 |
| PRECICE_GID | 1003 |
## Information about the machine
### uname -a
-Linux precice-tests 5.15.0-177-generic #187-Ubuntu SMP Sat Apr 11 22:54:33 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
### lscpu
diff --git a/flow-over-heated-plate/solid-dunefem/run.sh b/flow-over-heated-plate/solid-dunefem/run.sh
index 3c0c73f5c..87f9d6477 100755
--- a/flow-over-heated-plate/solid-dunefem/run.sh
+++ b/flow-over-heated-plate/solid-dunefem/run.sh
@@ -4,11 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
python3 solid.py
diff --git a/flow-over-heated-plate/solid-fenics/run.sh b/flow-over-heated-plate/solid-fenics/run.sh
index 3a0977996..1d0d38150 100755
--- a/flow-over-heated-plate/solid-fenics/run.sh
+++ b/flow-over-heated-plate/solid-fenics/run.sh
@@ -4,11 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv --system-site-package .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv --system-site-packages .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
python3 solid.py
diff --git a/flow-over-heated-plate/solid-fenicsx/clean.sh b/flow-over-heated-plate/solid-fenicsx/clean.sh
index 9413511cc..57d3ea1b0 100755
--- a/flow-over-heated-plate/solid-fenicsx/clean.sh
+++ b/flow-over-heated-plate/solid-fenicsx/clean.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env bash
set -e -u
. ../../tools/cleaning-tools.sh
diff --git a/flow-over-heated-plate/solid-fenicsx/requirements.txt b/flow-over-heated-plate/solid-fenicsx/requirements.txt
index b36876a55..a06d7331a 100644
--- a/flow-over-heated-plate/solid-fenicsx/requirements.txt
+++ b/flow-over-heated-plate/solid-fenicsx/requirements.txt
@@ -1,3 +1,3 @@
-numpy
-fenicsxprecice
+numpy >1, <2
+fenicsxprecice~=1.0
mpi4py>=3
diff --git a/flow-over-heated-plate/solid-fenicsx/run.sh b/flow-over-heated-plate/solid-fenicsx/run.sh
index a95847662..d339c8e23 100755
--- a/flow-over-heated-plate/solid-fenicsx/run.sh
+++ b/flow-over-heated-plate/solid-fenicsx/run.sh
@@ -1,8 +1,14 @@
-#!/bin/sh
+#!/usr/bin/env bash
set -e -u
-python3 -m venv --system-site-packages .venv
-. .venv/bin/activate
-pip install -r requirements.txt
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv --system-site-packages .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
+fi
python3 solid.py
diff --git a/flow-over-heated-plate/solid-nutils/requirements.txt b/flow-over-heated-plate/solid-nutils/requirements.txt
index 7ff7b5aa1..f22e7ac25 100644
--- a/flow-over-heated-plate/solid-nutils/requirements.txt
+++ b/flow-over-heated-plate/solid-nutils/requirements.txt
@@ -1,4 +1,4 @@
-setuptools # required by nutils
+setuptools>=69.0.0 # required by nutils
nutils~=7.3
numpy >1, <2
pyprecice~=3.0
diff --git a/flow-over-heated-plate/solid-nutils/run.sh b/flow-over-heated-plate/solid-nutils/run.sh
index 3c0c73f5c..87f9d6477 100755
--- a/flow-over-heated-plate/solid-nutils/run.sh
+++ b/flow-over-heated-plate/solid-nutils/run.sh
@@ -4,11 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
python3 solid.py
diff --git a/free-flow-over-porous-media/precice-config.xml b/free-flow-over-porous-media/precice-config.xml
index d06b2feec..09243353a 100644
--- a/free-flow-over-porous-media/precice-config.xml
+++ b/free-flow-over-porous-media/precice-config.xml
@@ -2,10 +2,9 @@
+ filter="%Severity% > debug and %Rank% = 0"
+ format="---[precice] %ColorizedSeverity% %Message%"
+ enabled="true" />
diff --git a/free-flow-over-porous-media/reference-results/free-flow-dumux_porous-media-dumux.tar.gz b/free-flow-over-porous-media/reference-results/free-flow-dumux_porous-media-dumux.tar.gz
index 7fd1bab2f..b736237f1 100644
--- a/free-flow-over-porous-media/reference-results/free-flow-dumux_porous-media-dumux.tar.gz
+++ b/free-flow-over-porous-media/reference-results/free-flow-dumux_porous-media-dumux.tar.gz
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:bc2e6a3137af7f16976b0731817170a7bf664255ddb4173e2c4d5c0319487cf4
-size 2288
+oid sha256:376f19f23b29d97dee96c0f6eda00d892a3bddd1deed521c919cc65b8c041f64
+size 1596
diff --git a/free-flow-over-porous-media/reference-results/reference_results.metadata b/free-flow-over-porous-media/reference-results/reference_results.metadata
index 0426fc1b1..0be5193d2 100644
--- a/free-flow-over-porous-media/reference-results/reference_results.metadata
+++ b/free-flow-over-porous-media/reference-results/reference_results.metadata
@@ -11,36 +11,36 @@ We also include some information on the machine used to generate them
| name | time | sha256 |
|------|------|-------|
-| free-flow-dumux_porous-media-dumux.tar.gz | 2026-05-11 07:45:27 | bc2e6a3137af7f16976b0731817170a7bf664255ddb4173e2c4d5c0319487cf4 |
+| free-flow-dumux_porous-media-dumux.tar.gz | 2026-05-28 11:46:06 | 376f19f23b29d97dee96c0f6eda00d892a3bddd1deed521c919cc65b8c041f64 |
## List of arguments used to generate the files
| name | value |
|------|------|
-| PRECICE_REF | d199bb3 |
-| PRECICE_PRESET | production-audit |
-| OPENFOAM_EXECUTABLE | openfoam2312 |
-| OPENFOAM_ADAPTER_REF | v1.3.1 |
-| PYTHON_BINDINGS_REF | v3.2.0 |
-| FENICS_ADAPTER_REF | v2.2.0 |
-| TUTORIALS_REF | b18b3ef |
| PLATFORM | ubuntu_2404 |
| CALCULIX_VERSION | 2.20 |
-| CALCULIX_ADAPTER_REF | v2.20.1 |
-| SU2_VERSION | 7.5.1 |
-| SU2_ADAPTER_REF | 64d4aff |
-| DEALII_ADAPTER_REF | 02c5d18 |
| DUNE_VERSION | 2.9 |
| DUMUX_VERSION | 3.7 |
-| DUMUX_ADAPTER_REF | 0e914bb |
-| MICRO_MANAGER_REF | v0.8.0 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | 9cb7068 |
+| PRECICE_PRESET | production-audit |
| PRECICE_UID | 1003 |
| PRECICE_GID | 1003 |
## Information about the machine
### uname -a
-Linux precice-tests 5.15.0-177-generic #187-Ubuntu SMP Sat Apr 11 22:54:33 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
### lscpu
diff --git a/heat-exchanger-simplified/reference-results/fluid-top-openfoam_fluid-bottom-openfoam_solid-calculix.tar.gz b/heat-exchanger-simplified/reference-results/fluid-top-openfoam_fluid-bottom-openfoam_solid-calculix.tar.gz
index ee8822064..1d13caaf9 100644
--- a/heat-exchanger-simplified/reference-results/fluid-top-openfoam_fluid-bottom-openfoam_solid-calculix.tar.gz
+++ b/heat-exchanger-simplified/reference-results/fluid-top-openfoam_fluid-bottom-openfoam_solid-calculix.tar.gz
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:5e440db6358e8582d12e83742f032e64574a83d72b583d914cf0aaa60c327438
-size 4344032
+oid sha256:1eb7b0fad4eb132608091ffa5350a0457dbfaae9c4993b42886eaf87a51de61e
+size 43432
diff --git a/heat-exchanger-simplified/reference-results/reference_results.metadata b/heat-exchanger-simplified/reference-results/reference_results.metadata
index b51259e49..1d6d2ffcb 100644
--- a/heat-exchanger-simplified/reference-results/reference_results.metadata
+++ b/heat-exchanger-simplified/reference-results/reference_results.metadata
@@ -11,36 +11,36 @@ We also include some information on the machine used to generate them
| name | time | sha256 |
|------|------|-------|
-| fluid-top-openfoam_fluid-bottom-openfoam_solid-calculix.tar.gz | 2026-05-11 07:45:27 | 5e440db6358e8582d12e83742f032e64574a83d72b583d914cf0aaa60c327438 |
+| fluid-top-openfoam_fluid-bottom-openfoam_solid-calculix.tar.gz | 2026-05-28 11:46:06 | 1eb7b0fad4eb132608091ffa5350a0457dbfaae9c4993b42886eaf87a51de61e |
## List of arguments used to generate the files
| name | value |
|------|------|
-| PRECICE_REF | d199bb3 |
-| PRECICE_PRESET | production-audit |
-| OPENFOAM_EXECUTABLE | openfoam2312 |
-| OPENFOAM_ADAPTER_REF | v1.3.1 |
-| PYTHON_BINDINGS_REF | v3.2.0 |
-| FENICS_ADAPTER_REF | v2.2.0 |
-| TUTORIALS_REF | b18b3ef |
| PLATFORM | ubuntu_2404 |
| CALCULIX_VERSION | 2.20 |
-| CALCULIX_ADAPTER_REF | v2.20.1 |
-| SU2_VERSION | 7.5.1 |
-| SU2_ADAPTER_REF | 64d4aff |
-| DEALII_ADAPTER_REF | 02c5d18 |
| DUNE_VERSION | 2.9 |
| DUMUX_VERSION | 3.7 |
-| DUMUX_ADAPTER_REF | 0e914bb |
-| MICRO_MANAGER_REF | v0.8.0 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | 9cb7068 |
+| PRECICE_PRESET | production-audit |
| PRECICE_UID | 1003 |
| PRECICE_GID | 1003 |
## Information about the machine
### uname -a
-Linux precice-tests 5.15.0-177-generic #187-Ubuntu SMP Sat Apr 11 22:54:33 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
### lscpu
diff --git a/heat-exchanger/.gitignore b/heat-exchanger/.gitignore
deleted file mode 100644
index 41190654c..000000000
--- a/heat-exchanger/.gitignore
+++ /dev/null
@@ -1,12 +0,0 @@
-# This case stores pre-generated meshes outside the repository
-solid-calculix/adiabatic.dfl
-solid-calculix/all.msh
-solid-calculix/inner-interface.flm
-solid-calculix/inner-interface.nam
-solid-calculix/inner-interface.sur
-solid-calculix/outer-interface.flm
-solid-calculix/outer-interface.nam
-solid-calculix/outer-interface.sur
-solid-calculix/solid.inp
-fluid-inner-openfoam/constant/polyMesh
-fluid-outer-openfoam/constant/polyMesh
diff --git a/heat-exchanger/README.md b/heat-exchanger/README.md
index b891a4580..c14ab5225 100644
--- a/heat-exchanger/README.md
+++ b/heat-exchanger/README.md
@@ -42,11 +42,9 @@ preCICE configuration (image generated using the [precice-config-visualizer](htt
## Running the Simulation
{% note %}
-Since the already prepared case contains mesh files of approx. 50MB in size, we currently host these files outside of the tutorials repository and you can download and extract them automatically in the appropriate locations by running the download-meshes.sh script. You can [help us improve this](https://github.com/precice/tutorials/issues/6)!
+Since the already prepared case contains mesh files of approx. 50MB in size, we currently host these files outside of the tutorials repository and are downloaded automatically the first time. You can [help us improve this](https://github.com/precice/tutorials/issues/6)!
{% endnote %}
-Before starting the simulation for the first time you need to download the mesh files and copy them into the appropriate location. The shell script `./download-meshes.sh` will handle these things automatically. Afterwards, the simulation setup is ready to run.
-
In order to run the coupled simulation, you can simply step into the participant directories and execute`./run.sh` (or `./run.sh -parallel` for running a fluid participant in parallel). The simulation will need several minutes or up to an hour on a laptop to end (t=500). Before repeating the simulation, you can use the `clean-tutorial.sh` script to clean-up any previous results and log files.
## Post-processing
diff --git a/heat-exchanger/download-meshes.sh b/heat-exchanger/download-meshes.sh
deleted file mode 100755
index 02f2a72f7..000000000
--- a/heat-exchanger/download-meshes.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/env sh
-
-echo "This tutorial is based on a case prepared with SimScale."
-echo "Since the mesh files are several MB large, we don't store them in the Git repository."
-echo "This script downloads and extracts the missing files."
-echo ""
-
-echo "Downloading the Solid case..."
-wget -nv -O - https://syncandshare.lrz.de/dl/fi3c9Xt5UzBc5hJvXzsLBHXn/Solid.tar.gz | tar -xzv
-mv ./Solid/* solid-calculix
-rm -r ./Solid
-sed -i 's/Solid/\./g' solid-calculix/solid.inp
-
-echo "Downloading and extracting the Inner-Fluid mesh..."
-wget -nv -O - https://syncandshare.lrz.de/dl/fiNsYGC1DKzgio4jS5NhsXg7/polyMesh.org.tar.gz | tar -xzv -C fluid-inner-openfoam/constant
-mv fluid-inner-openfoam/constant/polyMesh.org fluid-inner-openfoam/constant/polyMesh
-
-echo "Downloading and extracting the Outer-Fluid mesh..."
-wget -nv -O - https://syncandshare.lrz.de/dl/fiEZRQ8rcVWRkoyZvANim1R1/polyMesh.org.tar.gz | tar -xzv -C fluid-outer-openfoam/constant
-mv fluid-outer-openfoam/constant/polyMesh.org fluid-outer-openfoam/constant/polyMesh
-
-echo "Completed."
diff --git a/heat-exchanger/fluid-inner-openfoam/.gitignore b/heat-exchanger/fluid-inner-openfoam/.gitignore
new file mode 100644
index 000000000..8cd8f4a4c
--- /dev/null
+++ b/heat-exchanger/fluid-inner-openfoam/.gitignore
@@ -0,0 +1 @@
+constant/polyMesh
\ No newline at end of file
diff --git a/heat-exchanger/fluid-inner-openfoam/run.sh b/heat-exchanger/fluid-inner-openfoam/run.sh
index 3c9f805ce..353e8816a 100755
--- a/heat-exchanger/fluid-inner-openfoam/run.sh
+++ b/heat-exchanger/fluid-inner-openfoam/run.sh
@@ -4,6 +4,12 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
+if [ ! -f constant/polyMesh/boundary ]; then
+ echo "Downloading and extracting the Inner-Fluid mesh..."
+ wget -nv -O - https://syncandshare.lrz.de/dl/fiNsYGC1DKzgio4jS5NhsXg7/polyMesh.org.tar.gz | tar -xzv -C constant
+ mv constant/polyMesh.org constant/polyMesh
+fi
+
../../tools/run-openfoam.sh "$@"
. ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs
diff --git a/heat-exchanger/fluid-outer-openfoam/.gitignore b/heat-exchanger/fluid-outer-openfoam/.gitignore
new file mode 100644
index 000000000..8cd8f4a4c
--- /dev/null
+++ b/heat-exchanger/fluid-outer-openfoam/.gitignore
@@ -0,0 +1 @@
+constant/polyMesh
\ No newline at end of file
diff --git a/heat-exchanger/fluid-outer-openfoam/run.sh b/heat-exchanger/fluid-outer-openfoam/run.sh
index 3c9f805ce..fb3b7fa48 100755
--- a/heat-exchanger/fluid-outer-openfoam/run.sh
+++ b/heat-exchanger/fluid-outer-openfoam/run.sh
@@ -4,6 +4,12 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
+if [ ! -f constant/polyMesh/boundary ]; then
+ echo "Downloading and extracting the Outer-Fluid mesh..."
+ wget -nv -O - https://syncandshare.lrz.de/dl/fiEZRQ8rcVWRkoyZvANim1R1/polyMesh.org.tar.gz | tar -xzv -C constant
+ mv constant/polyMesh.org constant/polyMesh
+fi
+
../../tools/run-openfoam.sh "$@"
. ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs
diff --git a/heat-exchanger/metadata.yaml b/heat-exchanger/metadata.yaml
new file mode 100644
index 000000000..54974dd77
--- /dev/null
+++ b/heat-exchanger/metadata.yaml
@@ -0,0 +1,29 @@
+name: Heat exchanger
+path: heat-exchanger # relative to git repo
+url: https://precice.org/tutorials-heat-exchanger.html
+
+participants:
+ - Fluid-Inner
+ - Fluid-Outer
+ - Solid
+
+cases:
+ fluid-inner-openfoam:
+ participant: Fluid-Inner
+ directory: ./fluid-inner-openfoam
+ run: ./run.sh
+ component: openfoam-adapter
+
+ fluid-outer-openfoam:
+ participant: Fluid-Outer
+ directory: ./fluid-outer-openfoam
+ run: ./run.sh
+ component: openfoam-adapter
+
+ solid-calculix:
+ participant: Solid
+ directory: ./solid-calculix
+ run: ./run.sh
+ component: calculix-adapter
+
+
diff --git a/heat-exchanger/reference-results/fluid-inner-openfoam_solid-calculix_fluid-outer-openfoam.tar.gz b/heat-exchanger/reference-results/fluid-inner-openfoam_solid-calculix_fluid-outer-openfoam.tar.gz
new file mode 100644
index 000000000..74b595c0c
--- /dev/null
+++ b/heat-exchanger/reference-results/fluid-inner-openfoam_solid-calculix_fluid-outer-openfoam.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a7f1ffdb89cde47214eb1d97772c0d884c2b078d73578c7da27270b4463c8eb2
+size 13167591
diff --git a/heat-exchanger/reference-results/reference_results.metadata b/heat-exchanger/reference-results/reference_results.metadata
new file mode 100644
index 000000000..5f6f7148b
--- /dev/null
+++ b/heat-exchanger/reference-results/reference_results.metadata
@@ -0,0 +1,71 @@
+
+
+# Reference Results
+
+This file contains an overview of the results over the reference results as well as the arguments used to generate them.
+We also include some information on the machine used to generate them
+
+## List of files
+
+| name | time | sha256 |
+|------|------|-------|
+| fluid-inner-openfoam_solid-calculix_fluid-outer-openfoam.tar.gz | 2026-05-28 11:46:06 | a7f1ffdb89cde47214eb1d97772c0d884c2b078d73578c7da27270b4463c8eb2 |
+
+## List of arguments used to generate the files
+
+| name | value |
+|------|------|
+| PLATFORM | ubuntu_2404 |
+| CALCULIX_VERSION | 2.20 |
+| DUNE_VERSION | 2.9 |
+| DUMUX_VERSION | 3.7 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | 9cb7068 |
+| PRECICE_PRESET | production-audit |
+| PRECICE_UID | 1003 |
+| PRECICE_GID | 1003 |
+## Information about the machine
+
+### uname -a
+
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+
+
+### lscpu
+
+Architecture: x86_64
+CPU op-mode(s): 32-bit, 64-bit
+Address sizes: 45 bits physical, 48 bits virtual
+Byte Order: Little Endian
+CPU(s): 4
+On-line CPU(s) list: 0-3
+Vendor ID: GenuineIntel
+Model name: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz
+CPU family: 6
+Model: 85
+Thread(s) per core: 1
+Core(s) per socket: 1
+Socket(s): 4
+Stepping: 4
+BogoMIPS: 4199.99
+Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat pku ospke md_clear flush_l1d arch_capabilities
+Hypervisor vendor: VMware
+Virtualization type: full
+L1d cache: 128 KiB (4 instances)
+L1i cache: 128 KiB (4 instances)
+L2 cache: 4 MiB (4 instances)
+L3 cache: 88 MiB (4 instances)
+NUMA node(s): 1
+NUMA node0 CPU(s): 0-3
diff --git a/heat-exchanger/solid-calculix/.gitignore b/heat-exchanger/solid-calculix/.gitignore
new file mode 100644
index 000000000..b15ea7aaf
--- /dev/null
+++ b/heat-exchanger/solid-calculix/.gitignore
@@ -0,0 +1,10 @@
+# Files downloaded via run.sh
+adiabatic.dfl
+all.msh
+inner-interface.flm
+inner-interface.nam
+inner-interface.sur
+outer-interface.flm
+outer-interface.nam
+outer-interface.sur
+solid.inp
diff --git a/heat-exchanger/solid-calculix/run.sh b/heat-exchanger/solid-calculix/run.sh
index 1b1434904..00ade8ecc 100755
--- a/heat-exchanger/solid-calculix/run.sh
+++ b/heat-exchanger/solid-calculix/run.sh
@@ -5,8 +5,11 @@ set -e -u
exec > >(tee --append "$LOGFILE") 2>&1
if [ ! -f all.msh ]; then
- echo "Mesh files not found. Use the Download_meshes script to download them."
- exit
+ echo "Downloading the pre-processed Solid case..."
+ wget -nv -O - https://syncandshare.lrz.de/dl/fi3c9Xt5UzBc5hJvXzsLBHXn/Solid.tar.gz | tar -xzv
+ mv ./Solid/* .
+ rm -r ./Solid
+ sed -i 's/Solid/\./g' solid.inp
fi
export OMP_NUM_THREADS=1
diff --git a/multiple-perpendicular-flaps/reference-results/fluid-openfoam_solid-upstream-dealii_solid-downstream-dealii.tar.gz b/multiple-perpendicular-flaps/reference-results/fluid-openfoam_solid-upstream-dealii_solid-downstream-dealii.tar.gz
new file mode 100644
index 000000000..163ae0240
--- /dev/null
+++ b/multiple-perpendicular-flaps/reference-results/fluid-openfoam_solid-upstream-dealii_solid-downstream-dealii.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:53f71fb905f3714c4d30a963ba47139e1a93fa3ed3fc838856baa9fd81b949d7
+size 108391
diff --git a/multiple-perpendicular-flaps/reference-results/reference_results.metadata b/multiple-perpendicular-flaps/reference-results/reference_results.metadata
index c426ac97c..e6126cdb8 100644
--- a/multiple-perpendicular-flaps/reference-results/reference_results.metadata
+++ b/multiple-perpendicular-flaps/reference-results/reference_results.metadata
@@ -11,36 +11,36 @@ We also include some information on the machine used to generate them
| name | time | sha256 |
|------|------|-------|
-| fluid-openfoam_solid-upstream-dealii_solid-downstream-dealii.tar.gz | 2026-05-11 07:45:27 | ea2d5946f64667ba05ab3a3516cca7c3af3a59374ff22d0a69e0098c00c1ace1 |
+| fluid-openfoam_solid-upstream-dealii_solid-downstream-dealii.tar.gz | 2026-05-28 11:46:06 | 53f71fb905f3714c4d30a963ba47139e1a93fa3ed3fc838856baa9fd81b949d7 |
## List of arguments used to generate the files
| name | value |
|------|------|
-| PRECICE_REF | d199bb3 |
-| PRECICE_PRESET | production-audit |
-| OPENFOAM_EXECUTABLE | openfoam2312 |
-| OPENFOAM_ADAPTER_REF | v1.3.1 |
-| PYTHON_BINDINGS_REF | v3.2.0 |
-| FENICS_ADAPTER_REF | v2.2.0 |
-| TUTORIALS_REF | b18b3ef |
| PLATFORM | ubuntu_2404 |
| CALCULIX_VERSION | 2.20 |
-| CALCULIX_ADAPTER_REF | v2.20.1 |
-| SU2_VERSION | 7.5.1 |
-| SU2_ADAPTER_REF | 64d4aff |
-| DEALII_ADAPTER_REF | 02c5d18 |
| DUNE_VERSION | 2.9 |
| DUMUX_VERSION | 3.7 |
-| DUMUX_ADAPTER_REF | 0e914bb |
-| MICRO_MANAGER_REF | v0.8.0 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | 9cb7068 |
+| PRECICE_PRESET | production-audit |
| PRECICE_UID | 1003 |
| PRECICE_GID | 1003 |
## Information about the machine
### uname -a
-Linux precice-tests 5.15.0-177-generic #187-Ubuntu SMP Sat Apr 11 22:54:33 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
### lscpu
diff --git a/oscillator-overlap/mass-left-python/run.sh b/oscillator-overlap/mass-left-python/run.sh
index 8268553b8..2582e4270 100755
--- a/oscillator-overlap/mass-left-python/run.sh
+++ b/oscillator-overlap/mass-left-python/run.sh
@@ -4,9 +4,16 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-python3 -m venv .venv
-. .venv/bin/activate
-pip install -r ../solver-python/requirements.txt
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
+then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r ../solver-python/requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
+fi
python3 ../solver-python/oscillator.py Mass-Left
diff --git a/oscillator-overlap/mass-right-python/run.sh b/oscillator-overlap/mass-right-python/run.sh
index 51ddf0eac..be8fad2c5 100755
--- a/oscillator-overlap/mass-right-python/run.sh
+++ b/oscillator-overlap/mass-right-python/run.sh
@@ -4,9 +4,16 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-python3 -m venv .venv
-. .venv/bin/activate
-pip install -r ../solver-python/requirements.txt
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
+then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r ../solver-python/requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
+fi
python3 ../solver-python/oscillator.py Mass-Right
diff --git a/oscillator-overlap/metadata.yaml b/oscillator-overlap/metadata.yaml
new file mode 100644
index 000000000..9c77c5d7b
--- /dev/null
+++ b/oscillator-overlap/metadata.yaml
@@ -0,0 +1,20 @@
+name: Oscillator overlap
+path: oscillator-overlap
+url: https://precice.org/tutorials-oscillator-overlap.html
+
+participants:
+ - Mass-Left
+ - Mass-Right
+
+cases:
+ mass-left-python:
+ participant: Mass-Left
+ directory: ./mass-left-python
+ run: ./run.sh
+ component: python-bindings
+
+ mass-right-python:
+ participant: Mass-Right
+ directory: ./mass-right-python
+ run: ./run.sh
+ component: python-bindings
\ No newline at end of file
diff --git a/oscillator-overlap/precice-config.xml b/oscillator-overlap/precice-config.xml
index a09d28bde..5772202f9 100644
--- a/oscillator-overlap/precice-config.xml
+++ b/oscillator-overlap/precice-config.xml
@@ -1,7 +1,10 @@
-
-
+
+
diff --git a/oscillator-overlap/reference-results/mass-left-python_mass-right-python.tar.gz b/oscillator-overlap/reference-results/mass-left-python_mass-right-python.tar.gz
new file mode 100644
index 000000000..ba2019f4c
--- /dev/null
+++ b/oscillator-overlap/reference-results/mass-left-python_mass-right-python.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c04f630a7507838e7cb4b97d5af0ee1cf65a7055291e664603be3b8037f53ac3
+size 16098
diff --git a/oscillator-overlap/reference-results/reference_results.metadata b/oscillator-overlap/reference-results/reference_results.metadata
new file mode 100644
index 000000000..19dfb6793
--- /dev/null
+++ b/oscillator-overlap/reference-results/reference_results.metadata
@@ -0,0 +1,71 @@
+
+
+# Reference Results
+
+This file contains an overview of the results over the reference results as well as the arguments used to generate them.
+We also include some information on the machine used to generate them
+
+## List of files
+
+| name | time | sha256 |
+|------|------|-------|
+| mass-left-python_mass-right-python.tar.gz | 2026-05-30 14:00:24 | c04f630a7507838e7cb4b97d5af0ee1cf65a7055291e664603be3b8037f53ac3 |
+
+## List of arguments used to generate the files
+
+| name | value |
+|------|------|
+| PLATFORM | ubuntu_2404 |
+| CALCULIX_VERSION | 2.20 |
+| DUNE_VERSION | 2.9 |
+| DUMUX_VERSION | 3.7 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | 89c82d5 |
+| PRECICE_PRESET | production-audit |
+| PRECICE_UID | 1003 |
+| PRECICE_GID | 1003 |
+## Information about the machine
+
+### uname -a
+
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+
+
+### lscpu
+
+Architecture: x86_64
+CPU op-mode(s): 32-bit, 64-bit
+Address sizes: 45 bits physical, 48 bits virtual
+Byte Order: Little Endian
+CPU(s): 4
+On-line CPU(s) list: 0-3
+Vendor ID: GenuineIntel
+Model name: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz
+CPU family: 6
+Model: 85
+Thread(s) per core: 1
+Core(s) per socket: 1
+Socket(s): 4
+Stepping: 4
+BogoMIPS: 4199.99
+Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat pku ospke md_clear flush_l1d arch_capabilities
+Hypervisor vendor: VMware
+Virtualization type: full
+L1d cache: 128 KiB (4 instances)
+L1i cache: 128 KiB (4 instances)
+L2 cache: 4 MiB (4 instances)
+L3 cache: 88 MiB (4 instances)
+NUMA node(s): 1
+NUMA node0 CPU(s): 0-3
diff --git a/oscillator-overlap/solver-python/requirements.txt b/oscillator-overlap/solver-python/requirements.txt
index 9dff131c5..d61415287 100644
--- a/oscillator-overlap/solver-python/requirements.txt
+++ b/oscillator-overlap/solver-python/requirements.txt
@@ -1,3 +1,3 @@
numpy >1, <2
pyprecice~=3.0
-scipy
+scipy>=1.10,<2
diff --git a/oscillator/.gitignore b/oscillator/.gitignore
deleted file mode 100644
index 69310321e..000000000
--- a/oscillator/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-fmi/Oscillator.fmu
diff --git a/oscillator/mass-left-fmi/fmi-settings.json b/oscillator/mass-left-fmi/fmi-settings.json
index dc4d752c2..1b7006286 100644
--- a/oscillator/mass-left-fmi/fmi-settings.json
+++ b/oscillator/mass-left-fmi/fmi-settings.json
@@ -10,7 +10,7 @@
"mass.a": -197.392088022
},
"simulation_params": {
- "fmu_file_name": "../solver-fmi/Oscillator.fmu",
+ "fmu_file_name": "./Oscillator.fmu",
"output_file_name": "./output/trajectory-Mass-Left.csv",
"output": ["mass.u", "mass.v"],
"fmu_read_data_names": ["force_in"],
diff --git a/oscillator/mass-left-fmi/requirements.txt b/oscillator/mass-left-fmi/requirements.txt
index 10f7ea9df..3ff3bd9de 100644
--- a/oscillator/mass-left-fmi/requirements.txt
+++ b/oscillator/mass-left-fmi/requirements.txt
@@ -1 +1,2 @@
-fmiprecice
\ No newline at end of file
+fmiprecice~=0.2
+pandas>=2.0,<3
diff --git a/oscillator/mass-left-fmi/run.sh b/oscillator/mass-left-fmi/run.sh
index 2d8940011..9a7704943 100755
--- a/oscillator/mass-left-fmi/run.sh
+++ b/oscillator/mass-left-fmi/run.sh
@@ -4,23 +4,28 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -f ../solver-fmi/Oscillator.fmu ]; then
- cd ../solver-fmi/fmu
- rm -rf build
- mkdir build
- cd build
- # Both FMI_VERSION=3 and FMI_VERSION=2 are supported
- cmake -DFMI_TYPE=CS -DFMI_VERSION=3 ..
- make
- cp ./Oscillator.fmu ../..
- cd ../../../mass-left-fmi
+if [ ! -f Oscillator.fmu ]; then
+ echo "Building a copy of ../solver-fmi/fmu..."
+ (
+ cp -r ../solver-fmi _solver-fmi-copy
+ cd _solver-fmi-copy/fmu
+ rm -rf build && mkdir build && cd build
+ # Both FMI_VERSION=3 and FMI_VERSION=2 are supported
+ cmake -DFMI_TYPE=CS -DFMI_VERSION=3 ..
+ make
+ cp ./Oscillator.fmu ../../..
+ )
+ rm -r _solver-fmi-copy
fi
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
fmiprecice fmi-settings.json precice-settings.json
diff --git a/oscillator/mass-left-python/run.sh b/oscillator/mass-left-python/run.sh
index 8268553b8..2582e4270 100755
--- a/oscillator/mass-left-python/run.sh
+++ b/oscillator/mass-left-python/run.sh
@@ -4,9 +4,16 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-python3 -m venv .venv
-. .venv/bin/activate
-pip install -r ../solver-python/requirements.txt
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
+then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r ../solver-python/requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
+fi
python3 ../solver-python/oscillator.py Mass-Left
diff --git a/oscillator/mass-right-fmi/fmi-settings.json b/oscillator/mass-right-fmi/fmi-settings.json
index fc59edc20..3fdb5875b 100644
--- a/oscillator/mass-right-fmi/fmi-settings.json
+++ b/oscillator/mass-right-fmi/fmi-settings.json
@@ -10,7 +10,7 @@
"mass.a": 157.913670417
},
"simulation_params": {
- "fmu_file_name": "../solver-fmi/Oscillator.fmu",
+ "fmu_file_name": "./Oscillator.fmu",
"output_file_name": "./output/trajectory-Mass-Right.csv",
"output": ["mass.u", "mass.v"],
"fmu_read_data_names": ["force_in"],
diff --git a/oscillator/mass-right-fmi/requirements.txt b/oscillator/mass-right-fmi/requirements.txt
index 10f7ea9df..3ff3bd9de 100644
--- a/oscillator/mass-right-fmi/requirements.txt
+++ b/oscillator/mass-right-fmi/requirements.txt
@@ -1 +1,2 @@
-fmiprecice
\ No newline at end of file
+fmiprecice~=0.2
+pandas>=2.0,<3
diff --git a/oscillator/mass-right-fmi/run.sh b/oscillator/mass-right-fmi/run.sh
index 7cd85afd9..15b283e9e 100755
--- a/oscillator/mass-right-fmi/run.sh
+++ b/oscillator/mass-right-fmi/run.sh
@@ -4,23 +4,28 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -f ../solver-fmi/Oscillator.fmu ]; then
- cd ../solver-fmi/fmu
- rm -rf build
- mkdir build
- cd build
- # Both FMI_VERSION=3 and FMI_VERSION=2 are supported
- cmake -DFMI_TYPE=CS -DFMI_VERSION=3 ..
- make
- cp ./Oscillator.fmu ../..
- cd ../../../mass-right-fmi
+if [ ! -f Oscillator.fmu ]; then
+ echo "Building a copy of ../solver-fmi/fmu..."
+ (
+ cp -r ../solver-fmi _solver-fmi-copy
+ cd _solver-fmi-copy/fmu
+ rm -rf build && mkdir build && cd build
+ # Both FMI_VERSION=3 and FMI_VERSION=2 are supported
+ cmake -DFMI_TYPE=CS -DFMI_VERSION=3 ..
+ make
+ cp ./Oscillator.fmu ../../..
+ )
+ rm -r _solver-fmi-copy
fi
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
fmiprecice fmi-settings.json precice-settings.json
diff --git a/oscillator/mass-right-python/run.sh b/oscillator/mass-right-python/run.sh
index 51ddf0eac..be8fad2c5 100755
--- a/oscillator/mass-right-python/run.sh
+++ b/oscillator/mass-right-python/run.sh
@@ -4,9 +4,16 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-python3 -m venv .venv
-. .venv/bin/activate
-pip install -r ../solver-python/requirements.txt
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
+then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r ../solver-python/requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
+fi
python3 ../solver-python/oscillator.py Mass-Right
diff --git a/oscillator/metadata.yaml b/oscillator/metadata.yaml
new file mode 100644
index 000000000..3bff0dddd
--- /dev/null
+++ b/oscillator/metadata.yaml
@@ -0,0 +1,32 @@
+name: Oscillator
+path: oscillator
+url: https://precice.org/tutorials-oscillator.html
+
+participants:
+ - Mass-Left
+ - Mass-Right
+
+cases:
+ mass-left-fmi:
+ participant: Mass-Left
+ directory: ./mass-left-fmi
+ run: ./run.sh
+ component: python-bindings
+
+ mass-left-python:
+ participant: Mass-Left
+ directory: ./mass-left-python
+ run: ./run.sh
+ component: python-bindings
+
+ mass-right-fmi:
+ participant: Mass-Right
+ directory: ./mass-right-fmi
+ run: ./run.sh
+ component: python-bindings
+
+ mass-right-python:
+ participant: Mass-Right
+ directory: ./mass-right-python
+ run: ./run.sh
+ component: python-bindings
\ No newline at end of file
diff --git a/oscillator/precice-config.xml b/oscillator/precice-config.xml
index bfc1ffa92..afb6ac29f 100644
--- a/oscillator/precice-config.xml
+++ b/oscillator/precice-config.xml
@@ -1,7 +1,10 @@
-
-
+
+
diff --git a/oscillator/reference-results/mass-left-fmi_mass-right-fmi.tar.gz b/oscillator/reference-results/mass-left-fmi_mass-right-fmi.tar.gz
new file mode 100644
index 000000000..1c9cb4ca8
--- /dev/null
+++ b/oscillator/reference-results/mass-left-fmi_mass-right-fmi.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0655f286163324887695c6a8159e44471a9fb181e66da721f8c09c815d46f9d8
+size 15953
diff --git a/oscillator/reference-results/mass-left-python_mass-right-python.tar.gz b/oscillator/reference-results/mass-left-python_mass-right-python.tar.gz
new file mode 100644
index 000000000..57a77bf30
--- /dev/null
+++ b/oscillator/reference-results/mass-left-python_mass-right-python.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ceea3e0b2fa91501aad438012010115882b6a9264769d496d6c3a44d3471b7a9
+size 16275
diff --git a/oscillator/reference-results/reference_results.metadata b/oscillator/reference-results/reference_results.metadata
new file mode 100644
index 000000000..79eab4b47
--- /dev/null
+++ b/oscillator/reference-results/reference_results.metadata
@@ -0,0 +1,72 @@
+
+
+# Reference Results
+
+This file contains an overview of the results over the reference results as well as the arguments used to generate them.
+We also include some information on the machine used to generate them
+
+## List of files
+
+| name | time | sha256 |
+|------|------|-------|
+| mass-left-fmi_mass-right-fmi.tar.gz | 2026-05-30 14:40:41 | 0655f286163324887695c6a8159e44471a9fb181e66da721f8c09c815d46f9d8 |
+| mass-left-python_mass-right-python.tar.gz | 2026-05-30 14:40:41 | ceea3e0b2fa91501aad438012010115882b6a9264769d496d6c3a44d3471b7a9 |
+
+## List of arguments used to generate the files
+
+| name | value |
+|------|------|
+| PLATFORM | ubuntu_2404 |
+| CALCULIX_VERSION | 2.20 |
+| DUNE_VERSION | 2.9 |
+| DUMUX_VERSION | 3.7 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | 19f9523 |
+| PRECICE_PRESET | production-audit |
+| PRECICE_UID | 1003 |
+| PRECICE_GID | 1003 |
+## Information about the machine
+
+### uname -a
+
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+
+
+### lscpu
+
+Architecture: x86_64
+CPU op-mode(s): 32-bit, 64-bit
+Address sizes: 45 bits physical, 48 bits virtual
+Byte Order: Little Endian
+CPU(s): 4
+On-line CPU(s) list: 0-3
+Vendor ID: GenuineIntel
+Model name: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz
+CPU family: 6
+Model: 85
+Thread(s) per core: 1
+Core(s) per socket: 1
+Socket(s): 4
+Stepping: 4
+BogoMIPS: 4199.99
+Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat pku ospke md_clear flush_l1d arch_capabilities
+Hypervisor vendor: VMware
+Virtualization type: full
+L1d cache: 128 KiB (4 instances)
+L1i cache: 128 KiB (4 instances)
+L2 cache: 4 MiB (4 instances)
+L3 cache: 88 MiB (4 instances)
+NUMA node(s): 1
+NUMA node0 CPU(s): 0-3
diff --git a/oscillator/solver-fmi/requirements.txt b/oscillator/solver-fmi/requirements.txt
index 10f7ea9df..3ff3bd9de 100644
--- a/oscillator/solver-fmi/requirements.txt
+++ b/oscillator/solver-fmi/requirements.txt
@@ -1 +1,2 @@
-fmiprecice
\ No newline at end of file
+fmiprecice~=0.2
+pandas>=2.0,<3
diff --git a/oscillator/solver-python/requirements.txt b/oscillator/solver-python/requirements.txt
index 9dff131c5..d61415287 100644
--- a/oscillator/solver-python/requirements.txt
+++ b/oscillator/solver-python/requirements.txt
@@ -1,3 +1,3 @@
numpy >1, <2
pyprecice~=3.0
-scipy
+scipy>=1.10,<2
diff --git a/partitioned-backwards-facing-step/metadata.yaml b/partitioned-backwards-facing-step/metadata.yaml
new file mode 100644
index 000000000..982e273fd
--- /dev/null
+++ b/partitioned-backwards-facing-step/metadata.yaml
@@ -0,0 +1,20 @@
+name: Partitioned backwards facing step
+path: partitioned-backwards-facing-step # relative to git repo
+url: https://precice.org/tutorials-partitioned-backwards-facing-step.html
+
+participants:
+ - Fluid1
+ - Fluid2
+
+cases:
+ fluid1-openfoam:
+ participant: Fluid1
+ directory: ./fluid1-openfoam
+ run: ./run.sh
+ component: openfoam-adapter
+
+ fluid2-openfoam:
+ participant: Fluid2
+ directory: ./fluid2-openfoam
+ run: ./run.sh
+ component: openfoam-adapter
diff --git a/partitioned-backwards-facing-step/reference-results/fluid1-openfoam_fluid2-openfoam.tar.gz b/partitioned-backwards-facing-step/reference-results/fluid1-openfoam_fluid2-openfoam.tar.gz
new file mode 100644
index 000000000..3457c7ae4
--- /dev/null
+++ b/partitioned-backwards-facing-step/reference-results/fluid1-openfoam_fluid2-openfoam.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2c496201a6ec9533da240a31406513332da8aa95f6984ba93810980598b050e3
+size 199706
diff --git a/partitioned-backwards-facing-step/reference-results/reference_results.metadata b/partitioned-backwards-facing-step/reference-results/reference_results.metadata
new file mode 100644
index 000000000..f468d73fa
--- /dev/null
+++ b/partitioned-backwards-facing-step/reference-results/reference_results.metadata
@@ -0,0 +1,71 @@
+
+
+# Reference Results
+
+This file contains an overview of the results over the reference results as well as the arguments used to generate them.
+We also include some information on the machine used to generate them
+
+## List of files
+
+| name | time | sha256 |
+|------|------|-------|
+| fluid1-openfoam_fluid2-openfoam.tar.gz | 2026-05-30 22:27:06 | 2c496201a6ec9533da240a31406513332da8aa95f6984ba93810980598b050e3 |
+
+## List of arguments used to generate the files
+
+| name | value |
+|------|------|
+| PLATFORM | ubuntu_2404 |
+| CALCULIX_VERSION | 2.20 |
+| DUNE_VERSION | 2.9 |
+| DUMUX_VERSION | 3.7 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | more-tests |
+| PRECICE_PRESET | production-audit |
+| PRECICE_UID | 1003 |
+| PRECICE_GID | 1003 |
+## Information about the machine
+
+### uname -a
+
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+
+
+### lscpu
+
+Architecture: x86_64
+CPU op-mode(s): 32-bit, 64-bit
+Address sizes: 45 bits physical, 48 bits virtual
+Byte Order: Little Endian
+CPU(s): 4
+On-line CPU(s) list: 0-3
+Vendor ID: GenuineIntel
+Model name: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz
+CPU family: 6
+Model: 85
+Thread(s) per core: 1
+Core(s) per socket: 1
+Socket(s): 4
+Stepping: 4
+BogoMIPS: 4199.99
+Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat pku ospke md_clear flush_l1d arch_capabilities
+Hypervisor vendor: VMware
+Virtualization type: full
+L1d cache: 128 KiB (4 instances)
+L1i cache: 128 KiB (4 instances)
+L2 cache: 4 MiB (4 instances)
+L3 cache: 88 MiB (4 instances)
+NUMA node(s): 1
+NUMA node0 CPU(s): 0-3
diff --git a/partitioned-elastic-beam/dirichlet-calculix/config.yml b/partitioned-elastic-beam/dirichlet-calculix/config.yml
index 6cd31537c..519234353 100644
--- a/partitioned-elastic-beam/dirichlet-calculix/config.yml
+++ b/partitioned-elastic-beam/dirichlet-calculix/config.yml
@@ -1,9 +1,9 @@
participants:
- Calculix1:
+ Dirichlet:
interfaces:
- - nodes-mesh: Calculix-Mesh1
+ - nodes-mesh: Dirichlet-Mesh
patch: surface
- read-data: [Displacement0]
- write-data: [Force0]
+ read-data: [Displacement]
+ write-data: [Force]
precice-config-file: ../precice-config.xml
diff --git a/partitioned-elastic-beam/dirichlet-calculix/run.sh b/partitioned-elastic-beam/dirichlet-calculix/run.sh
index 50487ec03..9b100c3c5 100755
--- a/partitioned-elastic-beam/dirichlet-calculix/run.sh
+++ b/partitioned-elastic-beam/dirichlet-calculix/run.sh
@@ -6,6 +6,6 @@ exec > >(tee --append "$LOGFILE") 2>&1
export OMP_NUM_THREADS=1
export CCX_NPROC_EQUATION_SOLVER=1
-ccx_preCICE -i beam1 -precice-participant Calculix1
+ccx_preCICE -i beam1 -precice-participant Dirichlet
close_log
diff --git a/partitioned-elastic-beam/images/tutorials-partitioned-elastic-beam-precice-config.png b/partitioned-elastic-beam/images/tutorials-partitioned-elastic-beam-precice-config.png
index 24c552332..0871903cc 100644
Binary files a/partitioned-elastic-beam/images/tutorials-partitioned-elastic-beam-precice-config.png and b/partitioned-elastic-beam/images/tutorials-partitioned-elastic-beam-precice-config.png differ
diff --git a/partitioned-elastic-beam/metadata.yaml b/partitioned-elastic-beam/metadata.yaml
new file mode 100644
index 000000000..3d9788f88
--- /dev/null
+++ b/partitioned-elastic-beam/metadata.yaml
@@ -0,0 +1,20 @@
+name: Partitioned elastic beam
+path: partitioned-elastic-beam # relative to git repo
+url: https://precice.org/tutorials-partitioned-elastic-beam.html
+
+participants:
+ - Dirichlet
+ - Neumann
+
+cases:
+ dirichlet-calculix:
+ participant: Dirichlet
+ directory: ./dirichlet-calculix
+ run: ./run.sh
+ component: calculix-adapter
+
+ neumann-calculix:
+ participant: Neumann
+ directory: ./neumann-calculix
+ run: ./run.sh
+ component: calculix-adapter
\ No newline at end of file
diff --git a/partitioned-elastic-beam/neumann-calculix/config.yml b/partitioned-elastic-beam/neumann-calculix/config.yml
index 793f41626..ad7f1f320 100644
--- a/partitioned-elastic-beam/neumann-calculix/config.yml
+++ b/partitioned-elastic-beam/neumann-calculix/config.yml
@@ -1,9 +1,9 @@
participants:
- Calculix2:
+ Neumann:
interfaces:
- - nodes-mesh: Calculix-Mesh2
+ - nodes-mesh: Neumann-Mesh
patch: surface
- read-data: [Force0]
- write-data: [Displacement0]
+ read-data: [Force]
+ write-data: [Displacement]
precice-config-file: ../precice-config.xml
diff --git a/partitioned-elastic-beam/neumann-calculix/run.sh b/partitioned-elastic-beam/neumann-calculix/run.sh
index 7505fab51..49495abca 100755
--- a/partitioned-elastic-beam/neumann-calculix/run.sh
+++ b/partitioned-elastic-beam/neumann-calculix/run.sh
@@ -6,6 +6,6 @@ exec > >(tee --append "$LOGFILE") 2>&1
export OMP_NUM_THREADS=1
export CCX_NPROC_EQUATION_SOLVER=1
-ccx_preCICE -i beam2 -precice-participant Calculix2
+ccx_preCICE -i beam2 -precice-participant Neumann
close_log
diff --git a/partitioned-elastic-beam/precice-config.xml b/partitioned-elastic-beam/precice-config.xml
index 5a15f12ad..4d242c2bc 100644
--- a/partitioned-elastic-beam/precice-config.xml
+++ b/partitioned-elastic-beam/precice-config.xml
@@ -9,57 +9,56 @@
-
-
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
-
+
-
+
-
-
+
+
-
-
-
+
+
-
-
+
+
diff --git a/partitioned-elastic-beam/reference-results/dirichlet-calculix_neumann-calculix.tar.gz b/partitioned-elastic-beam/reference-results/dirichlet-calculix_neumann-calculix.tar.gz
new file mode 100644
index 000000000..442c24679
--- /dev/null
+++ b/partitioned-elastic-beam/reference-results/dirichlet-calculix_neumann-calculix.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d101821ef08ad7c0b2dae2b30d244ecac1b1c5d234ad01701ecf7567fff69fb3
+size 21541
diff --git a/partitioned-elastic-beam/reference-results/reference_results.metadata b/partitioned-elastic-beam/reference-results/reference_results.metadata
new file mode 100644
index 000000000..e7e3fe1ee
--- /dev/null
+++ b/partitioned-elastic-beam/reference-results/reference_results.metadata
@@ -0,0 +1,71 @@
+
+
+# Reference Results
+
+This file contains an overview of the results over the reference results as well as the arguments used to generate them.
+We also include some information on the machine used to generate them
+
+## List of files
+
+| name | time | sha256 |
+|------|------|-------|
+| dirichlet-calculix_neumann-calculix.tar.gz | 2026-05-28 15:36:00 | d101821ef08ad7c0b2dae2b30d244ecac1b1c5d234ad01701ecf7567fff69fb3 |
+
+## List of arguments used to generate the files
+
+| name | value |
+|------|------|
+| PLATFORM | ubuntu_2404 |
+| CALCULIX_VERSION | 2.20 |
+| DUNE_VERSION | 2.9 |
+| DUMUX_VERSION | 3.7 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | 0b8bea0 |
+| PRECICE_PRESET | production-audit |
+| PRECICE_UID | 1003 |
+| PRECICE_GID | 1003 |
+## Information about the machine
+
+### uname -a
+
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+
+
+### lscpu
+
+Architecture: x86_64
+CPU op-mode(s): 32-bit, 64-bit
+Address sizes: 45 bits physical, 48 bits virtual
+Byte Order: Little Endian
+CPU(s): 4
+On-line CPU(s) list: 0-3
+Vendor ID: GenuineIntel
+Model name: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz
+CPU family: 6
+Model: 85
+Thread(s) per core: 1
+Core(s) per socket: 1
+Socket(s): 4
+Stepping: 4
+BogoMIPS: 4199.99
+Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat pku ospke md_clear flush_l1d arch_capabilities
+Hypervisor vendor: VMware
+Virtualization type: full
+L1d cache: 128 KiB (4 instances)
+L1i cache: 128 KiB (4 instances)
+L2 cache: 4 MiB (4 instances)
+L3 cache: 88 MiB (4 instances)
+NUMA node(s): 1
+NUMA node0 CPU(s): 0-3
diff --git a/partitioned-heat-conduction-3d/README.md b/partitioned-heat-conduction-3d/README.md
new file mode 100644
index 000000000..eac1d6d56
--- /dev/null
+++ b/partitioned-heat-conduction-3d/README.md
@@ -0,0 +1,57 @@
+---
+title: 3D partitioned heat conduction
+permalink: tutorials-partitioned-heat-conduction-3d.html
+keywords: FEniCSx, Heat conduction
+summary: We solve a simple heat equation on a 3D domain. The domain is partitioned and the coupling is established in a Dirichlet-Neumann fashion.
+---
+
+{% note %}
+Get the [case files of this tutorial](https://github.com/precice/tutorials/tree/develop/partitioned-heat-conduction-3d), as continuously rendered here, or see the [latest released version](https://github.com/precice/tutorials/tree/master/partitioned-heat-conduction-3d) (if there is already one). Read how in the [tutorials introduction](https://precice.org/tutorials.html).
+{% endnote %}
+
+## Setup
+
+We solve a partitioned heat equation. For information on the two dimensional non-partitioned case, please refer to [1, p.37ff]. In this tutorial the computational domain is partitioned and coupled via preCICE. The coupling roughly follows the approach described in [2].
+
+
+
+The computational domain can be seen in the picture above. To get a better overview of the domain, the domains of the participants are translated.
+The domain of the Neumann participant is the small box, and the Dirichlet participant's domain is the rest. In the simulation, the small box is fully contained in the Dirichlet domain. This means, the coupling interface consists of five sides of the box.
+
+## Configuration
+
+preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)):
+
+
+
+## Available solvers and dependencies
+
+You can either couple a solver with itself or different solvers with each other. In any case you will need to have preCICE and the python bindings installed on your system.
+
+* FEniCSx. Install [FEniCS](https://fenicsproject.org/download/) and the [FEniCSx-adapter](https://github.com/precice/fenicsx-adapter). The code is adapted from the existing [fenics-tutorial](https://github.com/hplgit/fenics-tutorial/blob/master/pub/python/vol1/ft03_heat.py) from [1].
+
+## Running the simulation
+
+You can find the corresponding `run.sh` script for running the case in the folders corresponding to the participant you want to use:
+
+```bash
+cd dirichlet-fenicsx
+./run.sh
+```
+
+and
+
+```bash
+cd neumann-fenicsx
+./run.sh
+```
+
+## Visualization
+
+Output is written into the folders of the FEniCSx solvers (`neumann-fenicsx/output-neumann.bp` and `dirichlet-fenicsx/output-dirichlet.bp`).
+
+It is sufficient to import the folders to ParaView to get the visualization of the simulation.
+
+## References
+
+[1] Hans Petter Langtangen and Anders Logg. "Solving PDEs in Minutes-The FEniCS Tutorial Volume I." (2016). [pdf](https://fenicsproject.org/pub/tutorial/pdf/fenics-tutorial-vol1.pdf)
diff --git a/partitioned-heat-conduction-3d/clean-tutorial.sh b/partitioned-heat-conduction-3d/clean-tutorial.sh
new file mode 100755
index 000000000..56e40d689
--- /dev/null
+++ b/partitioned-heat-conduction-3d/clean-tutorial.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/env sh
+set -e -u
+
+# shellcheck disable=SC1091
+. ../tools/cleaning-tools.sh
+
+clean_tutorial .
+clean_precice_logs .
+rm -fv ./*.log
+
diff --git a/partitioned-heat-conduction-3d/dirichlet-fenicsx/clean.sh b/partitioned-heat-conduction-3d/dirichlet-fenicsx/clean.sh
new file mode 100755
index 000000000..46529f8d7
--- /dev/null
+++ b/partitioned-heat-conduction-3d/dirichlet-fenicsx/clean.sh
@@ -0,0 +1,6 @@
+#!/usr/bin/env sh
+set -e -u
+
+. ../../tools/cleaning-tools.sh
+
+clean_fenicsx .
diff --git a/partitioned-heat-conduction-3d/dirichlet-fenicsx/precice-adapter-config-D.json b/partitioned-heat-conduction-3d/dirichlet-fenicsx/precice-adapter-config-D.json
new file mode 100644
index 000000000..5976848e0
--- /dev/null
+++ b/partitioned-heat-conduction-3d/dirichlet-fenicsx/precice-adapter-config-D.json
@@ -0,0 +1,19 @@
+{
+ "participant_name": "Dirichlet",
+ "precice_config_file_path": "../precice-config.xml",
+ "interfaces": [
+ {
+ "mesh_name": "Dirichlet-Mesh",
+ "write_data": [
+ {
+ "name": "Heat-Flux"
+ }
+ ],
+ "read_data": [
+ {
+ "name": "Temperature"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/partitioned-heat-conduction-3d/dirichlet-fenicsx/run.sh b/partitioned-heat-conduction-3d/dirichlet-fenicsx/run.sh
new file mode 100755
index 000000000..0193545c4
--- /dev/null
+++ b/partitioned-heat-conduction-3d/dirichlet-fenicsx/run.sh
@@ -0,0 +1,15 @@
+#!/usr/bin/env bash
+set -e -u
+
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
+then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv --system-site-packages .venv
+ source .venv/bin/activate
+ pip install -r ../solver-fenicsx/requirements.txt
+ else
+ source .venv/bin/activate
+ fi
+fi
+
+python3 ../solver-fenicsx/heat.py Dirichlet --error-tol 10e-3
diff --git a/partitioned-heat-conduction-3d/images/tutorials-partitioned-heat-conduction-3d-precice-config.png b/partitioned-heat-conduction-3d/images/tutorials-partitioned-heat-conduction-3d-precice-config.png
new file mode 100644
index 000000000..bd9a35c71
Binary files /dev/null and b/partitioned-heat-conduction-3d/images/tutorials-partitioned-heat-conduction-3d-precice-config.png differ
diff --git a/partitioned-heat-conduction-3d/images/tutorials-partitioned-heat-conduction-3d-setup.png b/partitioned-heat-conduction-3d/images/tutorials-partitioned-heat-conduction-3d-setup.png
new file mode 100644
index 000000000..70a1d12df
Binary files /dev/null and b/partitioned-heat-conduction-3d/images/tutorials-partitioned-heat-conduction-3d-setup.png differ
diff --git a/partitioned-heat-conduction-3d/metadata.yaml b/partitioned-heat-conduction-3d/metadata.yaml
new file mode 100644
index 000000000..df957913f
--- /dev/null
+++ b/partitioned-heat-conduction-3d/metadata.yaml
@@ -0,0 +1,20 @@
+name: Partitioned heat conduction 3D
+path: partitioned-heat-conduction-3d # relative to git repo
+url: https://precice.org/tutorials-partitioned-heat-conduction-3d.html
+
+participants:
+ - Dirichlet
+ - Neumann
+
+cases:
+ dirichlet-fenicsx:
+ participant: Dirichlet
+ directory: ./dirichlet-fenicsx
+ run: ./run.sh
+ component: fenicsx-adapter
+
+ neumann-fenicsx:
+ participant: Neumann
+ directory: ./neumann-fenicsx
+ run: ./run.sh
+ component: fenicsx-adapter
diff --git a/partitioned-heat-conduction-3d/neumann-fenicsx/clean.sh b/partitioned-heat-conduction-3d/neumann-fenicsx/clean.sh
new file mode 100755
index 000000000..46529f8d7
--- /dev/null
+++ b/partitioned-heat-conduction-3d/neumann-fenicsx/clean.sh
@@ -0,0 +1,6 @@
+#!/usr/bin/env sh
+set -e -u
+
+. ../../tools/cleaning-tools.sh
+
+clean_fenicsx .
diff --git a/partitioned-heat-conduction-3d/neumann-fenicsx/precice-adapter-config-N.json b/partitioned-heat-conduction-3d/neumann-fenicsx/precice-adapter-config-N.json
new file mode 100644
index 000000000..dffe0e5e9
--- /dev/null
+++ b/partitioned-heat-conduction-3d/neumann-fenicsx/precice-adapter-config-N.json
@@ -0,0 +1,19 @@
+{
+ "participant_name": "Neumann",
+ "precice_config_file_path": "../precice-config.xml",
+ "interfaces": [
+ {
+ "mesh_name": "Neumann-Mesh",
+ "write_data": [
+ {
+ "name": "Temperature"
+ }
+ ],
+ "read_data": [
+ {
+ "name": "Heat-Flux"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/partitioned-heat-conduction-3d/neumann-fenicsx/run.sh b/partitioned-heat-conduction-3d/neumann-fenicsx/run.sh
new file mode 100755
index 000000000..21e98e115
--- /dev/null
+++ b/partitioned-heat-conduction-3d/neumann-fenicsx/run.sh
@@ -0,0 +1,15 @@
+#!/usr/bin/env bash
+set -e -u
+
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
+then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv --system-site-packages .venv
+ source .venv/bin/activate
+ pip install -r ../solver-fenicsx/requirements.txt
+ else
+ source .venv/bin/activate
+ fi
+fi
+
+python3 ../solver-fenicsx/heat.py Neumann --error-tol 10e-3
diff --git a/partitioned-heat-conduction-3d/precice-config.xml b/partitioned-heat-conduction-3d/precice-config.xml
new file mode 100644
index 000000000..d5c8ffdd6
--- /dev/null
+++ b/partitioned-heat-conduction-3d/precice-config.xml
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/partitioned-heat-conduction-3d/reference-results/dirichlet-fenicsx_neumann-fenicsx.tar.gz b/partitioned-heat-conduction-3d/reference-results/dirichlet-fenicsx_neumann-fenicsx.tar.gz
new file mode 100644
index 000000000..3b1070796
--- /dev/null
+++ b/partitioned-heat-conduction-3d/reference-results/dirichlet-fenicsx_neumann-fenicsx.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:9b6e18753223598093d66ed3de3187b1c3ab10b9dc0d002e4d4cde3eb1555dd7
+size 576415
diff --git a/partitioned-heat-conduction-3d/reference-results/reference_results.metadata b/partitioned-heat-conduction-3d/reference-results/reference_results.metadata
new file mode 100644
index 000000000..d908ff01b
--- /dev/null
+++ b/partitioned-heat-conduction-3d/reference-results/reference_results.metadata
@@ -0,0 +1,72 @@
+
+
+# Reference Results
+
+This file contains an overview of the results over the reference results as well as the arguments used to generate them.
+We also include some information on the machine used to generate them
+
+## List of files
+
+| name | time | sha256 |
+|------|------|-------|
+| dirichlet-fenicsx_neumann-fenicsx.tar.gz | 2026-06-12 20:46:28 | 9b6e18753223598093d66ed3de3187b1c3ab10b9dc0d002e4d4cde3eb1555dd7 |
+
+## List of arguments used to generate the files
+
+| name | value |
+|------|------|
+| PLATFORM | ubuntu_2404 |
+| CALCULIX_VERSION | 2.20 |
+| DUNE_VERSION | 2.9 |
+| DUMUX_VERSION | 3.7 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| FENICSX_ADAPTER_REF | v1.0.1 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | develop |
+| PRECICE_PRESET | production-audit |
+| PRECICE_UID | 1003 |
+| PRECICE_GID | 1003 |
+## Information about the machine
+
+### uname -a
+
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+
+
+### lscpu
+
+Architecture: x86_64
+CPU op-mode(s): 32-bit, 64-bit
+Address sizes: 45 bits physical, 48 bits virtual
+Byte Order: Little Endian
+CPU(s): 4
+On-line CPU(s) list: 0-3
+Vendor ID: GenuineIntel
+Model name: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz
+CPU family: 6
+Model: 85
+Thread(s) per core: 1
+Core(s) per socket: 1
+Socket(s): 4
+Stepping: 4
+BogoMIPS: 4199.99
+Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat pku ospke md_clear flush_l1d arch_capabilities
+Hypervisor vendor: VMware
+Virtualization type: full
+L1d cache: 128 KiB (4 instances)
+L1i cache: 128 KiB (4 instances)
+L2 cache: 4 MiB (4 instances)
+L3 cache: 88 MiB (4 instances)
+NUMA node(s): 1
+NUMA node0 CPU(s): 0-3
diff --git a/partitioned-heat-conduction-3d/solver-fenicsx/clean.sh b/partitioned-heat-conduction-3d/solver-fenicsx/clean.sh
new file mode 100755
index 000000000..bdd9995e1
--- /dev/null
+++ b/partitioned-heat-conduction-3d/solver-fenicsx/clean.sh
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+set -e -u
+
+. ../../tools/cleaning-tools.sh
+
+clean_fenicsx .
diff --git a/partitioned-heat-conduction-3d/solver-fenicsx/errorcomputation.py b/partitioned-heat-conduction-3d/solver-fenicsx/errorcomputation.py
new file mode 100644
index 000000000..c3d239216
--- /dev/null
+++ b/partitioned-heat-conduction-3d/solver-fenicsx/errorcomputation.py
@@ -0,0 +1,21 @@
+from dolfinx import fem
+import numpy as np
+from mpi4py import MPI
+import ufl
+
+
+def compute_errors(u_approx, u_ref, total_error_tol=10 ** -7):
+ mesh = u_ref.function_space.mesh
+ # Compute L2 error and error at nodes
+ error_L2 = np.sqrt(mesh.comm.allreduce(fem.assemble_scalar(fem.form((u_approx - u_ref)**2 * ufl.dx)), op=MPI.SUM))
+ if mesh.comm.rank == 0:
+ print(f"L2-error: {error_L2:.2e}")
+
+ # Compute values at mesh vertices
+ error_max = mesh.comm.allreduce(np.max(np.abs(u_approx.x.array - u_ref.x.array)), op=MPI.MAX)
+ if mesh.comm.rank == 0:
+ print(f"Error_max: {error_max:.2e}")
+
+ assert (error_L2 < total_error_tol)
+
+ return (error_L2, error_max)
diff --git a/partitioned-heat-conduction-3d/solver-fenicsx/heat.py b/partitioned-heat-conduction-3d/solver-fenicsx/heat.py
new file mode 100644
index 000000000..310e164ae
--- /dev/null
+++ b/partitioned-heat-conduction-3d/solver-fenicsx/heat.py
@@ -0,0 +1,311 @@
+"""
+The basic example is taken from "Langtangen, Hans Petter, and Anders Logg. Solving PDEs in Python: The FEniCS
+Tutorial I. Springer International Publishing, 2016."
+
+The example code has been extended with preCICE API calls, mixed boundary conditions to allow for a Dirichlet-Neumann
+coupling of two separate heat equations and the domain has been changed to three dimensions.
+It also has been adapted to be compatible with FEniCSx.
+
+The original source code can be found on https://jsdokken.com/dolfinx-tutorial/chapter2/heat_equation.html.
+
+Heat equation with Dirichlet conditions. (Dirichlet problem)
+ u'= Laplace(u) + f in the outer domain
+ u = u_C on the coupling boundary
+ u = u_D on the remaining boundary
+ u = u_0 at t = 0
+ u = 1 + x^2 + alpha*y^2 + \beta*t
+ f = beta - 2 - 2*alpha
+
+Heat equation with mixed boundary conditions. (Neumann problem)
+ u'= Laplace(u) + f in the inner domain
+ du/dn = f_N on the coupling boundary
+ u = u_D on the remaining boundary
+ u = u_0 at t = 0
+ u = 1 + x^2 + alpha*y^2 + \beta*t
+ f = beta - 2 - 2*alpha
+"""
+import argparse
+import numpy as np
+from mpi4py import MPI
+import basix.ufl
+from petsc4py import PETSc
+import ufl
+from dolfinx import fem, io
+from dolfinx.fem.petsc import assemble_matrix, assemble_vector, apply_lifting, create_vector, set_bc
+import basix
+from fenicsxprecice import Adapter, CouplingMesh
+from errorcomputation import compute_errors
+from my_enums import ProblemType, DomainPart
+from problem_setup import get_geometry
+
+
+class GradientSolver:
+ """
+ compute flux following http://hplgit.github.io/INF5620/doc/pub/fenics_tutorial1.1/tu2.html#tut-poisson-gradu
+ The solver has been changed since the original version from the link above introduces larger errors
+
+ :param V_g: Vector function space
+ :param u: solution where gradient is to be determined
+ """
+
+ def __init__(self, domain, V_g):
+ self.domain = domain,
+ self.V_g = V_g
+
+ w = ufl.TrialFunction(V_g)
+ self.v = ufl.TestFunction(V_g)
+ a = fem.form(ufl.inner(w, self.v) * ufl.dx)
+ self.A = assemble_matrix(a)
+ self.A.assemble()
+
+ self.solver = PETSc.KSP().create(domain.comm)
+ self.solver.setOperators(self.A)
+ self.solver.setType(PETSc.KSP.Type.PREONLY)
+ self.solver.getPC().setType(PETSc.PC.Type.LU)
+
+ self.returnValue = fem.Function(V_g)
+
+ def compute(self, u):
+ L = fem.form(ufl.inner(ufl.grad(u), self.v) * ufl.dx)
+ b = create_vector(fem.extract_function_spaces(L))
+ assemble_vector(b, L)
+ # In the assembly above, ranks did not communicate and therefore, the cells have incorrect values
+ # To resolve this, the values in the ghost region must be added to the values from the owner
+ b.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE)
+ self.solver.solve(b, self.returnValue.x.petsc_vec)
+ return self.returnValue
+
+
+# Parse arguments
+parser = argparse.ArgumentParser(description="Solving heat equation for simple or complex interface case")
+parser.add_argument("participantName", help="Name of the solver.", type=str, choices=[p.value for p in ProblemType])
+parser.add_argument("-e", "--error-tol", help="set error tolerance", type=float, default=10**-8,)
+args = parser.parse_args()
+# Init variables with arguments
+participant_name = args.participantName
+error_tol = args.error_tol
+
+comm = MPI.COMM_WORLD
+rank = comm.Get_rank()
+
+t = 0
+fenics_dt = 0.1
+alpha = 3
+beta = .25
+gamma = 1.2
+
+# define the domain
+if participant_name == ProblemType.DIRICHLET.value:
+ problem = ProblemType.DIRICHLET
+ domain_part = DomainPart.OUTER
+elif participant_name == ProblemType.NEUMANN.value:
+ problem = ProblemType.NEUMANN
+ domain_part = DomainPart.INNER
+
+# create domain and function space
+domain, coupling_boundary, remaining_boundary = get_geometry(domain_part, comm)
+V = fem.functionspace(domain, ("Lagrange", 2))
+element = basix.ufl.element("Lagrange", domain.topology.cell_name(), 1, shape=(domain.geometry.dim,))
+V_g = fem.functionspace(domain, element)
+V_coup = None
+if problem is ProblemType.DIRICHLET:
+ V_coup = V
+else:
+ V_coup = V_g
+
+
+class exact_solution():
+ # Define the exact solution
+ def __init__(self, alpha, beta, gamma, t):
+ self.alpha = alpha
+ self.beta = beta
+ self.gamma = gamma
+ self.t = t
+
+ def __call__(self, x):
+ return 1 + x[0]**2 + self.alpha * x[1]**2 + self.beta * x[2]**2 + self.gamma * self.t
+
+
+u_exact = exact_solution(alpha, beta, gamma, t)
+
+gradient_solver = GradientSolver(domain, V_g)
+
+# Define the boundary condition
+bcs = []
+u_D = fem.Function(V)
+u_D.interpolate(u_exact)
+tdim = domain.topology.dim
+fdim = tdim - 1
+domain.topology.create_connectivity(fdim, tdim)
+# dofs for the remaining boundary. Can be directly set to u_D
+dofs_remaining = fem.locate_dofs_geometrical(V, remaining_boundary)
+bc_D = fem.dirichletbc(u_D, dofs_remaining)
+bcs.append(bc_D)
+
+# dofs (and the corresponding coordinates) for the coupling boundary (coupling function space)
+# this is later used to read data from preCICE and update boundary condition
+dofs_coupling = fem.locate_dofs_geometrical(V_coup, coupling_boundary)
+dofs_coupling_coordinates = V_coup.tabulate_dof_coordinates()[dofs_coupling]
+
+if problem is ProblemType.DIRICHLET:
+ f_N = fem.Function(V_g)
+ f_N.interpolate(gradient_solver.compute(u_D))
+
+u_n = fem.Function(V) # IV and solution u for the n-th time step
+u_n.interpolate(u_exact)
+
+# initialise precice
+precice, precice_dt, initial_data = None, 0.0, None
+if problem is ProblemType.DIRICHLET:
+ precice = Adapter(adapter_config_filename="precice-adapter-config-D.json", mpi_comm=comm)
+else:
+ precice = Adapter(adapter_config_filename="precice-adapter-config-N.json", mpi_comm=comm, digit_cutoff=12)
+
+coupling_mesh = None
+if problem is ProblemType.DIRICHLET:
+ coupling_mesh = CouplingMesh("Dirichlet-Mesh", coupling_boundary, {"Temperature": V_coup}, {"Heat-Flux": f_N})
+ precice.initialize([coupling_mesh])
+elif problem is ProblemType.NEUMANN:
+ coupling_mesh = CouplingMesh("Neumann-Mesh", coupling_boundary, {"Heat-Flux": V_coup}, {"Temperature": u_D})
+ precice.initialize([coupling_mesh])
+
+# get precice's dt
+precice_dt = precice.get_max_time_step_size()
+dt = np.min([fenics_dt, precice_dt])
+
+
+# Define the variational formualation
+# As $f$ is a constant independent of $t$, we can define it as a constant.
+f = fem.Constant(domain, gamma - 2 - 2 * alpha - 2 * beta)
+# We can now create our variational formulation, with the bilinear form `a` and linear form `L`.
+u, v = ufl.TrialFunction(V), ufl.TestFunction(V)
+F = u * v * ufl.dx + dt * ufl.dot(ufl.grad(u), ufl.grad(v)) * ufl.dx - (u_n + dt * f) * v * ufl.dx
+
+name_read = None
+if problem is ProblemType.DIRICHLET:
+ name_read = "Temperature"
+ read_mesh = "Dirichlet-Mesh"
+else:
+ name_read = "Heat-Flux"
+ read_mesh = "Neumann-Mesh"
+
+coupling_function = fem.Function(V_coup)
+
+if problem is ProblemType.DIRICHLET:
+ # modify Dirichlet boundary condition on coupling interface
+ bc_coup = fem.dirichletbc(coupling_function, dofs_coupling)
+ bcs.append(bc_coup)
+if problem is ProblemType.NEUMANN:
+ # modify Neumann boundary condition on coupling interface, modify weak
+ # form correspondingly
+ n = ufl.FacetNormal(domain)
+ F -= dt * ufl.inner(coupling_function, n) * v * ufl.ds
+ coupling_function.interpolate(gradient_solver.compute(u_D))
+a = fem.form(ufl.lhs(F))
+L = fem.form(ufl.rhs(F))
+
+# ## Create the matrix and vector for the linear problem
+# To ensure that we are solving the variational problem efficiently, we
+# will create several structures which can reuse data, such as matrix
+# sparisty patterns. Especially note as the bilinear form `a` is
+# independent of time, we only need to assemble the matrix once.
+A = assemble_matrix(a, bcs=bcs)
+A.assemble()
+b = create_vector(fem.extract_function_spaces(L))
+uh = fem.Function(V)
+
+# ## Define a linear variational solver
+# We will use [PETSc](https://www.mcs.anl.gov/petsc/) to solve the
+# resulting linear algebra problem. We use the Python-API `petsc4py` to
+# define the solver. We will use a linear solver.
+solver = PETSc.KSP().create(domain.comm)
+solver.setOperators(A)
+solver.setType(PETSc.KSP.Type.PREONLY)
+solver.getPC().setType(PETSc.PC.Type.LU)
+
+if problem is ProblemType.DIRICHLET:
+ flux = fem.Function(V_g)
+
+# boundaries point as always to the end of the timestep
+u_exact.t += dt
+u_D.interpolate(u_exact)
+
+f_err = fem.Function(V)
+# create writer for output files
+vtxwriter = io.VTXWriter(MPI.COMM_WORLD, f"output-{problem.name}.bp".lower(), [f_err])
+vtxwriter.write(t)
+
+if problem is ProblemType.NEUMANN:
+ mappingToOriginalSpace = None
+ dofs_coupling_coordinates = None
+ Tmp, mappingToOriginalSpace = V_coup.sub(0).collapse()
+ dofs_subspace = fem.locate_dofs_geometrical(Tmp, coupling_boundary)
+ # to get the vector dof's (true) coordinates, it is sufficient to use the dof's coordinates of an arbitrary subspace
+ dofs_coupling_coordinates = V_coup.tabulate_dof_coordinates()[dofs_subspace]
+
+while precice.is_coupling_ongoing():
+
+ if precice.requires_writing_checkpoint():
+ precice.store_checkpoint(u_n, t, 0)
+
+ precice_dt = precice.get_max_time_step_size()
+ dt = np.min([fenics_dt, precice_dt])
+
+ # Update the coupling expression with the new read data
+ precice.read_data(read_mesh, name_read, dt, coupling_function)
+
+ # Update the right hand side reusing the initial vector
+ with b.localForm() as loc_b:
+ loc_b.set(0)
+ assemble_vector(b, L)
+
+ # Apply Dirichlet boundary condition to the vector (according to the tutorial, the lifting operation is used to preserve the symmetry of the matrix)
+ # Boundary condition bc should be updated by u_D.interpolate above, since
+ # this function is wrapped into the bc object
+ apply_lifting(b, [a], [bcs])
+ b.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE)
+ set_bc(b, bcs)
+
+ # Solve linear problem
+ solver.solve(b, uh.x.petsc_vec)
+ uh.x.scatter_forward()
+
+ # Write data to preCICE according to which problem is being solved
+ if problem is ProblemType.DIRICHLET:
+ # Dirichlet problem reads temperature and writes flux on boundary to Neumann problem
+ flux = gradient_solver.compute(uh)
+ flux.x.scatter_forward()
+ precice.write_data(coupling_mesh.get_name(), "Heat-Flux", flux)
+ elif problem is ProblemType.NEUMANN:
+ # Neumann problem reads flux and writes temperature on boundary to Dirichlet problem
+ precice.write_data(coupling_mesh.get_name(), "Temperature", uh)
+
+ precice.advance(dt)
+ precice_dt = precice.get_max_time_step_size()
+
+ # roll back to checkpoint
+ if precice.requires_reading_checkpoint():
+ u_cp, t_cp, _ = precice.retrieve_checkpoint()
+ u_n.x.array[:] = u_cp.x.array
+ t = t_cp
+ else: # update solution
+ # Update solution at previous time step (u_n)
+ u_n.x.array[:] = uh.x.array
+ f_err.x.array[:] = np.abs(u_n.x.array - u_D.x.array)
+ t += float(dt)
+ vtxwriter.write(t)
+
+ if precice.is_time_window_complete():
+ u_ref = fem.Function(V)
+ u_ref.interpolate(u_D)
+ error, error_pointwise = compute_errors(u_n, u_ref, 1e-4)
+ print("t = %.2f: L2 error on domain = %.3g" % (t, error))
+
+ # Update Dirichlet BC
+ u_exact.t += dt
+ u_D.interpolate(u_exact)
+ # TODO: update time dependent f (as soon as it is time dependent)!
+
+precice.finalize()
+
+vtxwriter.close()
diff --git a/partitioned-heat-conduction-3d/solver-fenicsx/my_enums.py b/partitioned-heat-conduction-3d/solver-fenicsx/my_enums.py
new file mode 100644
index 000000000..666ae348e
--- /dev/null
+++ b/partitioned-heat-conduction-3d/solver-fenicsx/my_enums.py
@@ -0,0 +1,17 @@
+from enum import Enum
+
+
+class ProblemType(Enum):
+ """
+ Enum defines problem type. Details see above.
+ """
+ DIRICHLET = "Dirichlet" # Dirichlet problem
+ NEUMANN = "Neumann" # Neumann problem
+
+
+class DomainPart(Enum):
+ """
+ Enum defines which part of the domain [x_left, x_right] x [y_bottom, y_top] we compute.
+ """
+ OUTER = 1 # left part of domain in simple interface case
+ INNER = 2 # right part of domain in simple interface case
diff --git a/partitioned-heat-conduction-3d/solver-fenicsx/problem_setup.py b/partitioned-heat-conduction-3d/solver-fenicsx/problem_setup.py
new file mode 100644
index 000000000..35719f452
--- /dev/null
+++ b/partitioned-heat-conduction-3d/solver-fenicsx/problem_setup.py
@@ -0,0 +1,131 @@
+"""
+Problem setup for partitioned-heat-conduction/fenicsx tutorial
+"""
+from dolfinx.io import gmsh as gmshio
+from dolfinx.mesh import DiagonalType, create_box
+import dolfinx.mesh
+from my_enums import DomainPart
+import numpy as np
+from mpi4py import MPI
+import gmsh
+
+
+def get_geometry(domain_part, communicator):
+ gmsh.initialize()
+ gmsh.model.add("HeatMesh")
+
+ if domain_part is DomainPart.OUTER:
+ # In this section the outer box of the domain is defined.
+ # It is a cuboid from (0,0,0) to (2,1,2) and has a cuboid cutout from (1, .25, .5) to (2, .75, 1.5)
+ # The coupling interface is the surface from the cutout.
+
+ # Definition of the coupling boundary
+ def coupling_bc(x):
+ tol = 1E-14
+ top = np.logical_and.reduce((
+ np.isclose(x[1], 0.75, atol=tol),
+ np.logical_or(x[0] >= 1, np.isclose(x[0], 1, tol)),
+ np.logical_or(x[2] >= 0.5, np.isclose(x[2], 0.5, tol)),
+ np.logical_or(x[2] <= 1.5, np.isclose(x[2], 1.5, tol))
+ ))
+
+ bot = np.logical_and.reduce((
+ np.isclose(x[1], 0.25, tol),
+ np.logical_or(x[0] >= 1, np.isclose(x[0], 1, tol)),
+ np.logical_or(x[2] >= 0.5, np.isclose(x[2], 0.5, tol)),
+ np.logical_or(x[2] <= 1.5, np.isclose(x[2], 1.5, tol))
+ ))
+
+ sideCenter = np.logical_and.reduce((
+ np.isclose(x[0], 1, tol),
+ x[1] >= 0.25,
+ x[1] <= 0.75,
+ x[2] >= 0.5,
+ x[2] <= 1.5
+ ))
+
+ sideLeft = np.logical_and.reduce((
+ x[0] >= 1,
+ x[1] >= 0.25,
+ x[1] <= 0.75,
+ np.isclose(x[2], 0.5, tol)
+ ))
+
+ sideRight = np.logical_and.reduce((
+ x[0] >= 1,
+ x[1] >= 0.25,
+ x[1] <= 0.75,
+ np.isclose(x[2], 1.5, tol)
+ ))
+
+ return np.logical_or.reduce((top, bot, sideCenter, sideLeft, sideRight))
+
+ # definition of the boundary excluding the coupling boundary
+
+ def boundary_bc(x):
+ tol = 1E-14
+ or_part = np.logical_or.reduce((
+ np.isclose(x[0], 0, tol),
+ np.isclose(x[0], 2, tol),
+ np.isclose(x[1], 0, tol),
+ np.isclose(x[1], 1, tol),
+ np.isclose(x[2], 0, tol),
+ np.isclose(x[2], 2, tol)
+ ))
+ and_part = np.logical_and.reduce((
+ np.isclose(x[0], 2, tol),
+ x[1] >= 0.25,
+ x[1] <= 0.75,
+ x[2] >= 0.5,
+ x[2] <= 1.5,
+
+ ))
+ return np.logical_and(or_part, ~and_part)
+
+ # for creating the mesh, gmsh is used
+ # create full cuboid
+ gmsh.model.occ.addBox(0, 0, 0, 2, 1, 2, 1)
+ gmsh.model.occ.synchronize()
+ # create cuboid for cutout
+ gmsh.model.occ.addBox(1, 0.25, .5, 1, .5, 1, 2)
+ gmsh.model.occ.synchronize()
+
+ # remove smaller cuboid from large cuboid
+ _, _ = gmsh.model.occ.cut([(3, 1)], [(3, 2)], 3, True, True)
+ gmsh.model.occ.synchronize()
+ gmsh.model.addPhysicalGroup(3, [3], 4, "foo")
+ # generate mesh with max. edge length of 0.15
+ gmsh.model.mesh.setOrder(2)
+ gmsh.option.setNumber("Mesh.CharacteristicLengthMax", 0.15)
+ gmsh.model.mesh.generate(3)
+ # convert from gmsh to a dolfinx representation
+ outer_mesh = gmshio.model_to_mesh(gmsh.model, communicator, 0, 3).mesh
+ gmsh.finalize()
+ return outer_mesh, coupling_bc, boundary_bc
+ else:
+ # inner part of the domain
+ # it is defined by a cuboid from (1, .25, .5) to (2, .75, 1.5)
+
+ # 5 sides of the cuboid define the coupling interface
+ def coupling_bc(x):
+ tol = 1E-14
+ return np.logical_or(
+ np.logical_or(np.isclose(x[1], 0.75, tol), np.isclose(x[1], 0.25, tol)),
+ np.logical_or(np.isclose(x[0], 1, tol),
+ np.logical_or(np.isclose(x[2], 0.5, tol), np.isclose(x[2], 1.5, tol))))
+
+ def boundary_bc(x):
+ tol = 1E-14
+ return np.isclose(x[0], 2, tol)
+
+ # create cuboid
+ gmsh.model.occ.addBox(1, 0.25, .5, 1, .5, 1, 1)
+ gmsh.model.occ.synchronize()
+ gmsh.model.addPhysicalGroup(3, [1], 2, "foo")
+ # generate mesh
+ gmsh.model.mesh.setOrder(2)
+ gmsh.model.mesh.generate(3)
+ # convert from gmsh to dolfinx representation
+ inner_mesh = gmshio.model_to_mesh(gmsh.model, communicator, 0, 3).mesh
+ gmsh.finalize()
+ return inner_mesh, coupling_bc, boundary_bc
diff --git a/partitioned-heat-conduction-3d/solver-fenicsx/requirements.txt b/partitioned-heat-conduction-3d/solver-fenicsx/requirements.txt
new file mode 100644
index 000000000..0c528ba4b
--- /dev/null
+++ b/partitioned-heat-conduction-3d/solver-fenicsx/requirements.txt
@@ -0,0 +1,5 @@
+numpy >1, <2
+fenicsxprecice~=1.0
+scipy>=1.10,<2
+sympy>=1.10,<2
+gmsh>=4,<5
diff --git a/partitioned-heat-conduction-3d/solver-fenicsx/run.sh b/partitioned-heat-conduction-3d/solver-fenicsx/run.sh
new file mode 100755
index 000000000..731545f5f
--- /dev/null
+++ b/partitioned-heat-conduction-3d/solver-fenicsx/run.sh
@@ -0,0 +1,28 @@
+#!/usr/bin/env bash
+set -e -u
+
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
+then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv --system-site-packages .venv
+ source .venv/bin/activate
+ pip install ../../..
+ pip install -r .requirements.txt
+ else
+ source .venv/bin/activate
+ fi
+fi
+
+while getopts ":dn" opt; do
+ case ${opt} in
+ d)
+ python3 heat.py Dirichlet --error-tol 10e-3
+ ;;
+ n)
+ python3 heat.py Neumann --error-tol 10e-3
+ ;;
+ \?)
+ echo "Usage: cmd [-d] [-n]"
+ ;;
+ esac
+done
diff --git a/partitioned-heat-conduction-complex/dirichlet-fenics/run.sh b/partitioned-heat-conduction-complex/dirichlet-fenics/run.sh
index feccfc7b7..02bae5076 100755
--- a/partitioned-heat-conduction-complex/dirichlet-fenics/run.sh
+++ b/partitioned-heat-conduction-complex/dirichlet-fenics/run.sh
@@ -6,8 +6,10 @@ exec > >(tee --append "$LOGFILE") 2>&1
if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
then
- python3 -m venv --system-site-packages .venv
- . .venv/bin/activate
+ if [ ! -d ".venv" ]; then
+ python3 -m venv --system-site-packages .venv
+ fi
+ source .venv/bin/activate
pip install -r ../solver-fenics/requirements.txt
fi
diff --git a/partitioned-heat-conduction-complex/metadata.yaml b/partitioned-heat-conduction-complex/metadata.yaml
new file mode 100644
index 000000000..673a612b3
--- /dev/null
+++ b/partitioned-heat-conduction-complex/metadata.yaml
@@ -0,0 +1,20 @@
+name: Partitioned heat conduction complex
+path: partitioned-heat-conduction-complex # relative to git repo
+url: https://precice.org/tutorials-partitioned-heat-conduction-complex.html
+
+participants:
+ - Dirichlet
+ - Neumann
+
+cases:
+ dirichlet-fenics:
+ participant: Dirichlet
+ directory: ./dirichlet-fenics
+ run: ./run.sh
+ component: fenics-adapter
+
+ neumann-fenics:
+ participant: Neumann
+ directory: ./neumann-fenics
+ run: ./run.sh
+ component: fenics-adapter
diff --git a/partitioned-heat-conduction-complex/neumann-fenics/run.sh b/partitioned-heat-conduction-complex/neumann-fenics/run.sh
index e505b7711..df26e7195 100755
--- a/partitioned-heat-conduction-complex/neumann-fenics/run.sh
+++ b/partitioned-heat-conduction-complex/neumann-fenics/run.sh
@@ -6,8 +6,10 @@ exec > >(tee --append "$LOGFILE") 2>&1
if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
then
- python3 -m venv --system-site-packages .venv
- . .venv/bin/activate
+ if [ ! -d ".venv" ]; then
+ python3 -m venv --system-site-packages .venv
+ fi
+ source .venv/bin/activate
pip install -r ../solver-fenics/requirements.txt
fi
diff --git a/partitioned-heat-conduction-complex/reference-results/dirichlet-fenics_neumann-fenics.tar.gz b/partitioned-heat-conduction-complex/reference-results/dirichlet-fenics_neumann-fenics.tar.gz
new file mode 100644
index 000000000..c0b63f3b5
--- /dev/null
+++ b/partitioned-heat-conduction-complex/reference-results/dirichlet-fenics_neumann-fenics.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:585f3f212d365a7a5183b37f0175a42ce98ec9f5c23b2ef1606bfb76199b4d24
+size 13001
diff --git a/partitioned-heat-conduction-complex/reference-results/reference_results.metadata b/partitioned-heat-conduction-complex/reference-results/reference_results.metadata
new file mode 100644
index 000000000..8d475a966
--- /dev/null
+++ b/partitioned-heat-conduction-complex/reference-results/reference_results.metadata
@@ -0,0 +1,71 @@
+
+
+# Reference Results
+
+This file contains an overview of the results over the reference results as well as the arguments used to generate them.
+We also include some information on the machine used to generate them
+
+## List of files
+
+| name | time | sha256 |
+|------|------|-------|
+| dirichlet-fenics_neumann-fenics.tar.gz | 2026-05-28 17:44:13 | 585f3f212d365a7a5183b37f0175a42ce98ec9f5c23b2ef1606bfb76199b4d24 |
+
+## List of arguments used to generate the files
+
+| name | value |
+|------|------|
+| PLATFORM | ubuntu_2404 |
+| CALCULIX_VERSION | 2.20 |
+| DUNE_VERSION | 2.9 |
+| DUMUX_VERSION | 3.7 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | 7a5a9c9 |
+| PRECICE_PRESET | production-audit |
+| PRECICE_UID | 1003 |
+| PRECICE_GID | 1003 |
+## Information about the machine
+
+### uname -a
+
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+
+
+### lscpu
+
+Architecture: x86_64
+CPU op-mode(s): 32-bit, 64-bit
+Address sizes: 45 bits physical, 48 bits virtual
+Byte Order: Little Endian
+CPU(s): 4
+On-line CPU(s) list: 0-3
+Vendor ID: GenuineIntel
+Model name: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz
+CPU family: 6
+Model: 85
+Thread(s) per core: 1
+Core(s) per socket: 1
+Socket(s): 4
+Stepping: 4
+BogoMIPS: 4199.99
+Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat pku ospke md_clear flush_l1d arch_capabilities
+Hypervisor vendor: VMware
+Virtualization type: full
+L1d cache: 128 KiB (4 instances)
+L1i cache: 128 KiB (4 instances)
+L2 cache: 4 MiB (4 instances)
+L3 cache: 88 MiB (4 instances)
+NUMA node(s): 1
+NUMA node0 CPU(s): 0-3
diff --git a/partitioned-heat-conduction-complex/solver-fenics/requirements.txt b/partitioned-heat-conduction-complex/solver-fenics/requirements.txt
index 04561a50f..9c23e91cf 100644
--- a/partitioned-heat-conduction-complex/solver-fenics/requirements.txt
+++ b/partitioned-heat-conduction-complex/solver-fenics/requirements.txt
@@ -1,6 +1,6 @@
fenicsprecice~=2.0
numpy >1, <2
-sympy
+sympy>=1.10,<2
# Assuming FEniCS from ppa:fenics-packages/fenics was installed https://fenicsproject.org/download/archive/
# Use --system-site-packages in venv
diff --git a/partitioned-heat-conduction-direct/README.md b/partitioned-heat-conduction-direct/README.md
index 80faa5fca..3826c1397 100644
--- a/partitioned-heat-conduction-direct/README.md
+++ b/partitioned-heat-conduction-direct/README.md
@@ -23,9 +23,15 @@ preCICE configuration (image generated using the [precice-config-visualizer](htt

+The data mapping is computed by directly sampling the FEM function representation at the inquired locations.
+
## Available solvers
-Currently only `nutils` is provided as a solver. The data mapping is computed by directly sampling the FEM function representation at the inquired locations.
+You can either couple a solver with itself or different solvers with each other. Available solvers:
+
+- Nutils. For more information, have a look at the [Nutils adapter documentation](https://precice.org/adapter-nutils.html).
+
+- G+Smo. Install the [G+Smo adapter](https://precice.org/adapter-gismo.html).
## Running the simulation
diff --git a/partitioned-heat-conduction-direct/dirichlet-nutils/requirements.txt b/partitioned-heat-conduction-direct/dirichlet-nutils/requirements.txt
index 7ff7b5aa1..f22e7ac25 100644
--- a/partitioned-heat-conduction-direct/dirichlet-nutils/requirements.txt
+++ b/partitioned-heat-conduction-direct/dirichlet-nutils/requirements.txt
@@ -1,4 +1,4 @@
-setuptools # required by nutils
+setuptools>=69.0.0 # required by nutils
nutils~=7.3
numpy >1, <2
pyprecice~=3.0
diff --git a/partitioned-heat-conduction-direct/dirichlet-nutils/run.sh b/partitioned-heat-conduction-direct/dirichlet-nutils/run.sh
index 2d3ff34db..8dd9c5c2a 100755
--- a/partitioned-heat-conduction-direct/dirichlet-nutils/run.sh
+++ b/partitioned-heat-conduction-direct/dirichlet-nutils/run.sh
@@ -4,11 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
rm -rf Dirichlet-*.vtk
diff --git a/partitioned-heat-conduction-direct/metadata.yaml b/partitioned-heat-conduction-direct/metadata.yaml
new file mode 100644
index 000000000..7bab6e103
--- /dev/null
+++ b/partitioned-heat-conduction-direct/metadata.yaml
@@ -0,0 +1,32 @@
+name: Partitioned heat conduction direct
+path: partitioned-heat-conduction-direct # relative to git repo
+url: https://precice.org/tutorials-partitioned-heat-conduction-direct.html
+
+participants:
+ - Dirichlet
+ - Neumann
+
+cases:
+ dirichlet-nutils:
+ participant: Dirichlet
+ directory: ./dirichlet-nutils
+ run: ./run.sh
+ component: nutils-adapter
+
+ # dirichlet-gismo:
+ # participant: Dirichlet
+ # directory: ./dirichlet-gismo
+ # run: ./run.sh
+ # component: gismo-adapter
+
+ neumann-nutils:
+ participant: Neumann
+ directory: ./neumann-nutils
+ run: ./run.sh
+ component: nutils-adapter
+
+ # neumann-gismo:
+ # participant: Neumann
+ # directory: ./neumann-gismo
+ # run: ./run.sh
+ # component: gismo-adapter
diff --git a/partitioned-heat-conduction-direct/neumann-nutils/requirements.txt b/partitioned-heat-conduction-direct/neumann-nutils/requirements.txt
index 7ff7b5aa1..f22e7ac25 100644
--- a/partitioned-heat-conduction-direct/neumann-nutils/requirements.txt
+++ b/partitioned-heat-conduction-direct/neumann-nutils/requirements.txt
@@ -1,4 +1,4 @@
-setuptools # required by nutils
+setuptools>=69.0.0 # required by nutils
nutils~=7.3
numpy >1, <2
pyprecice~=3.0
diff --git a/partitioned-heat-conduction-direct/neumann-nutils/run.sh b/partitioned-heat-conduction-direct/neumann-nutils/run.sh
index 54734b5f9..b072f8bb4 100755
--- a/partitioned-heat-conduction-direct/neumann-nutils/run.sh
+++ b/partitioned-heat-conduction-direct/neumann-nutils/run.sh
@@ -4,11 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
rm -rf Neumann-*.vtk
diff --git a/partitioned-heat-conduction-direct/reference-results/dirichlet-nutils_neumann-nutils.tar.gz b/partitioned-heat-conduction-direct/reference-results/dirichlet-nutils_neumann-nutils.tar.gz
new file mode 100644
index 000000000..16f367108
--- /dev/null
+++ b/partitioned-heat-conduction-direct/reference-results/dirichlet-nutils_neumann-nutils.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:404199906b36767490361dda293bb33e5a2d68dcce6d5aa74d4f0fd9a04f30fe
+size 1981
diff --git a/partitioned-heat-conduction-direct/reference-results/reference_results.metadata b/partitioned-heat-conduction-direct/reference-results/reference_results.metadata
new file mode 100644
index 000000000..31fcfacbf
--- /dev/null
+++ b/partitioned-heat-conduction-direct/reference-results/reference_results.metadata
@@ -0,0 +1,71 @@
+
+
+# Reference Results
+
+This file contains an overview of the results over the reference results as well as the arguments used to generate them.
+We also include some information on the machine used to generate them
+
+## List of files
+
+| name | time | sha256 |
+|------|------|-------|
+| dirichlet-nutils_neumann-nutils.tar.gz | 2026-05-30 14:00:24 | 404199906b36767490361dda293bb33e5a2d68dcce6d5aa74d4f0fd9a04f30fe |
+
+## List of arguments used to generate the files
+
+| name | value |
+|------|------|
+| PLATFORM | ubuntu_2404 |
+| CALCULIX_VERSION | 2.20 |
+| DUNE_VERSION | 2.9 |
+| DUMUX_VERSION | 3.7 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | 89c82d5 |
+| PRECICE_PRESET | production-audit |
+| PRECICE_UID | 1003 |
+| PRECICE_GID | 1003 |
+## Information about the machine
+
+### uname -a
+
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+
+
+### lscpu
+
+Architecture: x86_64
+CPU op-mode(s): 32-bit, 64-bit
+Address sizes: 45 bits physical, 48 bits virtual
+Byte Order: Little Endian
+CPU(s): 4
+On-line CPU(s) list: 0-3
+Vendor ID: GenuineIntel
+Model name: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz
+CPU family: 6
+Model: 85
+Thread(s) per core: 1
+Core(s) per socket: 1
+Socket(s): 4
+Stepping: 4
+BogoMIPS: 4199.99
+Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat pku ospke md_clear flush_l1d arch_capabilities
+Hypervisor vendor: VMware
+Virtualization type: full
+L1d cache: 128 KiB (4 instances)
+L1i cache: 128 KiB (4 instances)
+L2 cache: 4 MiB (4 instances)
+L3 cache: 88 MiB (4 instances)
+NUMA node(s): 1
+NUMA node0 CPU(s): 0-3
diff --git a/partitioned-heat-conduction-overlap/left-fenics/run.sh b/partitioned-heat-conduction-overlap/left-fenics/run.sh
index b19c1f5d9..49156c5d6 100755
--- a/partitioned-heat-conduction-overlap/left-fenics/run.sh
+++ b/partitioned-heat-conduction-overlap/left-fenics/run.sh
@@ -6,9 +6,13 @@ exec > >(tee --append "$LOGFILE") 2>&1
if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
then
- python3 -m venv --system-site-packages .venv
- . .venv/bin/activate
- pip install -r ../solver-fenics/requirements.txt
+ if [ ! -d ".venv" ]; then
+ python3 -m venv --system-site-packages .venv
+ source .venv/bin/activate
+ pip install -r ../solver-fenics/requirements.txt
+ else
+ source .venv/bin/activate
+ fi
fi
python3 ../solver-fenics/heat.py Left
diff --git a/partitioned-heat-conduction-overlap/metadata.yaml b/partitioned-heat-conduction-overlap/metadata.yaml
new file mode 100644
index 000000000..2e5ea2404
--- /dev/null
+++ b/partitioned-heat-conduction-overlap/metadata.yaml
@@ -0,0 +1,20 @@
+name: Partitioned heat conduction overlap
+path: partitioned-heat-conduction-overlap # relative to git repo
+url: https://precice.org/tutorials-partitioned-heat-conduction-overlap.html
+
+participants:
+ - Left
+ - Right
+
+cases:
+ left-fenics:
+ participant: Left
+ directory: ./left-fenics
+ run: ./run.sh
+ component: fenics-adapter
+
+ right-fenics:
+ participant: Right
+ directory: ./right-fenics
+ run: ./run.sh
+ component: fenics-adapter
diff --git a/partitioned-heat-conduction-overlap/reference-results/left-fenics_right-fenics.tar.gz b/partitioned-heat-conduction-overlap/reference-results/left-fenics_right-fenics.tar.gz
new file mode 100644
index 000000000..ad1581f87
--- /dev/null
+++ b/partitioned-heat-conduction-overlap/reference-results/left-fenics_right-fenics.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:995fcea6e3ab2983fc33724d0efc8d316fd346f135aa7e0c97e5652f6e06859b
+size 6871
diff --git a/partitioned-heat-conduction-overlap/reference-results/reference_results.metadata b/partitioned-heat-conduction-overlap/reference-results/reference_results.metadata
new file mode 100644
index 000000000..bfef8bcc3
--- /dev/null
+++ b/partitioned-heat-conduction-overlap/reference-results/reference_results.metadata
@@ -0,0 +1,71 @@
+
+
+# Reference Results
+
+This file contains an overview of the results over the reference results as well as the arguments used to generate them.
+We also include some information on the machine used to generate them
+
+## List of files
+
+| name | time | sha256 |
+|------|------|-------|
+| left-fenics_right-fenics.tar.gz | 2026-05-30 14:00:24 | 995fcea6e3ab2983fc33724d0efc8d316fd346f135aa7e0c97e5652f6e06859b |
+
+## List of arguments used to generate the files
+
+| name | value |
+|------|------|
+| PLATFORM | ubuntu_2404 |
+| CALCULIX_VERSION | 2.20 |
+| DUNE_VERSION | 2.9 |
+| DUMUX_VERSION | 3.7 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | 89c82d5 |
+| PRECICE_PRESET | production-audit |
+| PRECICE_UID | 1003 |
+| PRECICE_GID | 1003 |
+## Information about the machine
+
+### uname -a
+
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+
+
+### lscpu
+
+Architecture: x86_64
+CPU op-mode(s): 32-bit, 64-bit
+Address sizes: 45 bits physical, 48 bits virtual
+Byte Order: Little Endian
+CPU(s): 4
+On-line CPU(s) list: 0-3
+Vendor ID: GenuineIntel
+Model name: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz
+CPU family: 6
+Model: 85
+Thread(s) per core: 1
+Core(s) per socket: 1
+Socket(s): 4
+Stepping: 4
+BogoMIPS: 4199.99
+Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat pku ospke md_clear flush_l1d arch_capabilities
+Hypervisor vendor: VMware
+Virtualization type: full
+L1d cache: 128 KiB (4 instances)
+L1i cache: 128 KiB (4 instances)
+L2 cache: 4 MiB (4 instances)
+L3 cache: 88 MiB (4 instances)
+NUMA node(s): 1
+NUMA node0 CPU(s): 0-3
diff --git a/partitioned-heat-conduction-overlap/right-fenics/run.sh b/partitioned-heat-conduction-overlap/right-fenics/run.sh
index b8f73ac22..3c985c42a 100755
--- a/partitioned-heat-conduction-overlap/right-fenics/run.sh
+++ b/partitioned-heat-conduction-overlap/right-fenics/run.sh
@@ -6,9 +6,13 @@ exec > >(tee --append "$LOGFILE") 2>&1
if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
then
- python3 -m venv --system-site-packages .venv
- . .venv/bin/activate
- pip install -r ../solver-fenics/requirements.txt
+ if [ ! -d ".venv" ]; then
+ python3 -m venv --system-site-packages .venv
+ source .venv/bin/activate
+ pip install -r ../solver-fenics/requirements.txt
+ else
+ source .venv/bin/activate
+ fi
fi
python3 ../solver-fenics/heat.py Right
diff --git a/partitioned-heat-conduction/README.md b/partitioned-heat-conduction/README.md
index dabdfc66a..8b390f7f9 100644
--- a/partitioned-heat-conduction/README.md
+++ b/partitioned-heat-conduction/README.md
@@ -29,13 +29,13 @@ preCICE configuration (image generated using the [precice-config-visualizer](htt
## Available solvers and dependencies
-You can either couple a solver with itself or different solvers with each other. In any case you will need to have preCICE and the python bindings installed on your system.
+You can either couple a solver with itself or different solvers with each other. Available solvers:
* FEniCS. Install [FEniCS](https://fenicsproject.org/download/archive/) and the [FEniCS-adapter](https://github.com/precice/fenics-adapter). The code is largely based on this [fenics-tutorial](https://github.com/hplgit/fenics-tutorial/blob/master/pub/python/vol1/ft03_heat.py) from [1].
* FEniCSx. Install [FEniCSx](https://fenicsproject.org/download/) and the [FEniCSx-adapter](https://github.com/precice/fenicsx-adapter). The code is largely based on this [fenics-tutorial](https://github.com/hplgit/fenics-tutorial/blob/master/pub/python/vol1/ft03_heat.py) from [1].
-* Nutils. Install [Nutils](https://nutils.org/install-nutils.html).
+* Nutils. For more information, have a look at the [Nutils adapter documentation](https://precice.org/adapter-nutils.html).
* OpenFOAM. This case uses the custom [heatTransfer](https://github.com/precice/tutorials/blob/master/partitioned-heat-conduction/solver-openfoam/heatTransfer.C) solver (find it in `solver-openfoam` and build with `wmake`). Read more details in the [OpenFOAM adapter](https://precice.org/adapter-openfoam-overview.html).
diff --git a/partitioned-heat-conduction/dirichlet-fenics/run.sh b/partitioned-heat-conduction/dirichlet-fenics/run.sh
index 880f966a2..f0ae51182 100755
--- a/partitioned-heat-conduction/dirichlet-fenics/run.sh
+++ b/partitioned-heat-conduction/dirichlet-fenics/run.sh
@@ -4,11 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv --system-site-packages .venv
- . .venv/bin/activate
- pip install -r ../solver-fenics/requirements.txt
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv --system-site-packages .venv
+ source .venv/bin/activate
+ pip install -r ../solver-fenics/requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
if [ $# -eq 0 ]
diff --git a/partitioned-heat-conduction/dirichlet-fenicsx/run.sh b/partitioned-heat-conduction/dirichlet-fenicsx/run.sh
index cc7202ffb..f18697619 100755
--- a/partitioned-heat-conduction/dirichlet-fenicsx/run.sh
+++ b/partitioned-heat-conduction/dirichlet-fenicsx/run.sh
@@ -1,8 +1,14 @@
-#!/bin/sh
+#!/usr/bin/env bash
set -e -u
-python3 -m venv --system-site-packages .venv
-. .venv/bin/activate
-pip install -r ../solver-fenicsx/requirements.txt
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv --system-site-packages .venv
+ source .venv/bin/activate
+ pip install -r ../solver-fenicsx/requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
+fi
python3 ../solver-fenicsx/heat.py Dirichlet
diff --git a/partitioned-heat-conduction/dirichlet-nutils/requirements.txt b/partitioned-heat-conduction/dirichlet-nutils/requirements.txt
index 7ff7b5aa1..f22e7ac25 100644
--- a/partitioned-heat-conduction/dirichlet-nutils/requirements.txt
+++ b/partitioned-heat-conduction/dirichlet-nutils/requirements.txt
@@ -1,4 +1,4 @@
-setuptools # required by nutils
+setuptools>=69.0.0 # required by nutils
nutils~=7.3
numpy >1, <2
pyprecice~=3.0
diff --git a/partitioned-heat-conduction/dirichlet-nutils/run.sh b/partitioned-heat-conduction/dirichlet-nutils/run.sh
index 2d3ff34db..8dd9c5c2a 100755
--- a/partitioned-heat-conduction/dirichlet-nutils/run.sh
+++ b/partitioned-heat-conduction/dirichlet-nutils/run.sh
@@ -4,11 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
rm -rf Dirichlet-*.vtk
diff --git a/partitioned-heat-conduction/dirichlet-openfoam/run.sh b/partitioned-heat-conduction/dirichlet-openfoam/run.sh
index 8f55fbfa5..f53e6cd52 100755
--- a/partitioned-heat-conduction/dirichlet-openfoam/run.sh
+++ b/partitioned-heat-conduction/dirichlet-openfoam/run.sh
@@ -4,6 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
+# Build the heatTransfer solver, if not found.
+if ! command -v heatTransfer > /dev/null 2>&1; then
+ echo "Building ../solver-openfoam in a temporary build directory and installing to ${FOAM_USER_APPBIN}/heatTransfer..."
+ cp -r ../solver-openfoam ./_solver-openfoam-copy
+ wmake ./_solver-openfoam-copy
+ rm -r ./_solver-openfoam-copy
+fi
+
blockMesh
../../tools/run-openfoam.sh "$@"
diff --git a/partitioned-heat-conduction/metadata.yaml b/partitioned-heat-conduction/metadata.yaml
new file mode 100644
index 000000000..b7c058970
--- /dev/null
+++ b/partitioned-heat-conduction/metadata.yaml
@@ -0,0 +1,68 @@
+name: Partitioned heat conduction
+path: partitioned-heat-conduction # relative to git repo
+url: https://precice.org/tutorials-partitioned-heat-conduction.html
+
+participants:
+ - Dirichlet
+ - Neumann
+
+cases:
+ dirichlet-fenics:
+ participant: Dirichlet
+ directory: ./dirichlet-fenics
+ run: ./run.sh
+ component: fenics-adapter
+
+ dirichlet-fenicsx:
+ participant: Dirichlet
+ directory: ./dirichlet-fenicsx
+ run: ./run.sh
+ component: fenicsx-adapter
+
+ # dirichlet-gismo:
+ # participant: Dirichlet
+ # directory: ./dirichlet-gismo
+ # run: ./run.sh
+ # component: gismo-adapter
+
+ dirichlet-nutils:
+ participant: Dirichlet
+ directory: ./dirichlet-nutils
+ run: ./run.sh
+ component: nutils-adapter
+
+ dirichlet-openfoam:
+ participant: Dirichlet
+ directory: ./dirichlet-openfoam
+ run: ./run.sh
+ component: openfoam-adapter
+
+ neumann-fenics:
+ participant: Neumann
+ directory: ./neumann-fenics
+ run: ./run.sh
+ component: fenics-adapter
+
+ neumann-fenicsx:
+ participant: Neumann
+ directory: ./neumann-fenicsx
+ run: ./run.sh
+ component: fenicsx-adapter
+
+ # neumann-gismo:
+ # participant: Neumann
+ # directory: ./neumann-gismo
+ # run: ./run.sh
+ # component: gismo-adapter
+
+ neumann-nutils:
+ participant: Neumann
+ directory: ./neumann-nutils
+ run: ./run.sh
+ component: nutils-adapter
+
+ neumann-openfoam:
+ participant: Neumann
+ directory: ./neumann-openfoam
+ run: ./run.sh
+ component: openfoam-adapter
\ No newline at end of file
diff --git a/partitioned-heat-conduction/neumann-fenics/run.sh b/partitioned-heat-conduction/neumann-fenics/run.sh
index cc7a42c41..cb8940be6 100755
--- a/partitioned-heat-conduction/neumann-fenics/run.sh
+++ b/partitioned-heat-conduction/neumann-fenics/run.sh
@@ -4,11 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv --system-site-packages .venv
- . .venv/bin/activate
- pip install -r ../solver-fenics/requirements.txt
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv --system-site-packages .venv
+ source .venv/bin/activate
+ pip install -r ../solver-fenics/requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
python3 ../solver-fenics/heat.py Neumann
diff --git a/partitioned-heat-conduction/neumann-fenicsx/run.sh b/partitioned-heat-conduction/neumann-fenicsx/run.sh
index b676e0c94..0ba6e8b47 100755
--- a/partitioned-heat-conduction/neumann-fenicsx/run.sh
+++ b/partitioned-heat-conduction/neumann-fenicsx/run.sh
@@ -1,7 +1,14 @@
-#!/bin/sh
+#!/usr/bin/env bash
set -e -u
-python3 -m venv --system-site-packages .venv
-. .venv/bin/activate
-pip install -r ../solver-fenicsx/requirements.txt
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv --system-site-packages .venv
+ source .venv/bin/activate
+ pip install -r ../solver-fenicsx/requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
+fi
+
python3 ../solver-fenicsx/heat.py Neumann
diff --git a/partitioned-heat-conduction/neumann-nutils/requirements.txt b/partitioned-heat-conduction/neumann-nutils/requirements.txt
index 7ff7b5aa1..f22e7ac25 100644
--- a/partitioned-heat-conduction/neumann-nutils/requirements.txt
+++ b/partitioned-heat-conduction/neumann-nutils/requirements.txt
@@ -1,4 +1,4 @@
-setuptools # required by nutils
+setuptools>=69.0.0 # required by nutils
nutils~=7.3
numpy >1, <2
pyprecice~=3.0
diff --git a/partitioned-heat-conduction/neumann-nutils/run.sh b/partitioned-heat-conduction/neumann-nutils/run.sh
index 54734b5f9..b072f8bb4 100755
--- a/partitioned-heat-conduction/neumann-nutils/run.sh
+++ b/partitioned-heat-conduction/neumann-nutils/run.sh
@@ -4,11 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
rm -rf Neumann-*.vtk
diff --git a/partitioned-heat-conduction/neumann-openfoam/run.sh b/partitioned-heat-conduction/neumann-openfoam/run.sh
index 8f55fbfa5..f53e6cd52 100755
--- a/partitioned-heat-conduction/neumann-openfoam/run.sh
+++ b/partitioned-heat-conduction/neumann-openfoam/run.sh
@@ -4,6 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
+# Build the heatTransfer solver, if not found.
+if ! command -v heatTransfer > /dev/null 2>&1; then
+ echo "Building ../solver-openfoam in a temporary build directory and installing to ${FOAM_USER_APPBIN}/heatTransfer..."
+ cp -r ../solver-openfoam ./_solver-openfoam-copy
+ wmake ./_solver-openfoam-copy
+ rm -r ./_solver-openfoam-copy
+fi
+
blockMesh
../../tools/run-openfoam.sh "$@"
diff --git a/partitioned-heat-conduction/reference-results/dirichlet-fenics_neumann-fenics.tar.gz b/partitioned-heat-conduction/reference-results/dirichlet-fenics_neumann-fenics.tar.gz
new file mode 100644
index 000000000..18880c0d8
--- /dev/null
+++ b/partitioned-heat-conduction/reference-results/dirichlet-fenics_neumann-fenics.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6d2123f020ee4cddf89fb05fdd6e7abeb8f16cb33cca4a74ca7cfafceabcd91b
+size 2145
diff --git a/partitioned-heat-conduction/reference-results/dirichlet-fenicsx_neumann-fenicsx.tar.gz b/partitioned-heat-conduction/reference-results/dirichlet-fenicsx_neumann-fenicsx.tar.gz
new file mode 100644
index 000000000..5b6fd6906
--- /dev/null
+++ b/partitioned-heat-conduction/reference-results/dirichlet-fenicsx_neumann-fenicsx.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:034a8b34ab2f4d003d53d5f07aedc8b76aa52dc63788aac80a78e72cdd2e59a2
+size 4593
diff --git a/partitioned-heat-conduction/reference-results/dirichlet-nutils_neumann-nutils.tar.gz b/partitioned-heat-conduction/reference-results/dirichlet-nutils_neumann-nutils.tar.gz
new file mode 100644
index 000000000..93dcba28a
--- /dev/null
+++ b/partitioned-heat-conduction/reference-results/dirichlet-nutils_neumann-nutils.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:031a3bcc9a9d6d55ea4715b29e0c1a939bf522f1bf9cce048625590ab9fa3792
+size 2761
diff --git a/partitioned-heat-conduction/reference-results/dirichlet-openfoam_neumann-openfoam.tar.gz b/partitioned-heat-conduction/reference-results/dirichlet-openfoam_neumann-openfoam.tar.gz
new file mode 100644
index 000000000..ba9874a09
--- /dev/null
+++ b/partitioned-heat-conduction/reference-results/dirichlet-openfoam_neumann-openfoam.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:12a281982b1dc08e7fd9092dd5b30110ccc5f5db5b76594d60e7186b38d5fcbb
+size 6964
diff --git a/partitioned-heat-conduction/reference-results/reference_results.metadata b/partitioned-heat-conduction/reference-results/reference_results.metadata
new file mode 100644
index 000000000..d9636303a
--- /dev/null
+++ b/partitioned-heat-conduction/reference-results/reference_results.metadata
@@ -0,0 +1,72 @@
+
+
+# Reference Results
+
+This file contains an overview of the results over the reference results as well as the arguments used to generate them.
+We also include some information on the machine used to generate them
+
+## List of files
+
+| name | time | sha256 |
+|------|------|-------|
+| dirichlet-fenicsx_neumann-fenicsx.tar.gz | 2026-06-12 17:50:05 | 034a8b34ab2f4d003d53d5f07aedc8b76aa52dc63788aac80a78e72cdd2e59a2 |
+
+## List of arguments used to generate the files
+
+| name | value |
+|------|------|
+| PLATFORM | ubuntu_2404 |
+| CALCULIX_VERSION | 2.20 |
+| DUNE_VERSION | 2.9 |
+| DUMUX_VERSION | 3.7 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| FENICSX_ADAPTER_REF | v1.0.1 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | c1c5b4a3b044b5401d06f933204ff41e3252cedc |
+| PRECICE_PRESET | production-audit |
+| PRECICE_UID | 1003 |
+| PRECICE_GID | 1003 |
+## Information about the machine
+
+### uname -a
+
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+
+
+### lscpu
+
+Architecture: x86_64
+CPU op-mode(s): 32-bit, 64-bit
+Address sizes: 45 bits physical, 48 bits virtual
+Byte Order: Little Endian
+CPU(s): 4
+On-line CPU(s) list: 0-3
+Vendor ID: GenuineIntel
+Model name: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz
+CPU family: 6
+Model: 85
+Thread(s) per core: 1
+Core(s) per socket: 1
+Socket(s): 4
+Stepping: 4
+BogoMIPS: 4199.99
+Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat pku ospke md_clear flush_l1d arch_capabilities
+Hypervisor vendor: VMware
+Virtualization type: full
+L1d cache: 128 KiB (4 instances)
+L1i cache: 128 KiB (4 instances)
+L2 cache: 4 MiB (4 instances)
+L3 cache: 88 MiB (4 instances)
+NUMA node(s): 1
+NUMA node0 CPU(s): 0-3
diff --git a/partitioned-heat-conduction/solver-fenics/requirements.txt b/partitioned-heat-conduction/solver-fenics/requirements.txt
index 190ff55e4..b7f8077bd 100644
--- a/partitioned-heat-conduction/solver-fenics/requirements.txt
+++ b/partitioned-heat-conduction/solver-fenics/requirements.txt
@@ -1,6 +1,6 @@
numpy >1, <2
fenicsprecice~=2.0
-scipy
+scipy>=1.10,<2
# Assuming FEniCS from ppa:fenics-packages/fenics was installed https://fenicsproject.org/download/archive/
# Use --system-site-packages in venv
diff --git a/partitioned-heat-conduction/solver-fenicsx/clean.sh b/partitioned-heat-conduction/solver-fenicsx/clean.sh
index a5aeebd18..bdd9995e1 100755
--- a/partitioned-heat-conduction/solver-fenicsx/clean.sh
+++ b/partitioned-heat-conduction/solver-fenicsx/clean.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env bash
set -e -u
. ../../tools/cleaning-tools.sh
diff --git a/partitioned-heat-conduction/solver-fenicsx/requirements.txt b/partitioned-heat-conduction/solver-fenicsx/requirements.txt
index 85fc7389a..2985d2c89 100644
--- a/partitioned-heat-conduction/solver-fenicsx/requirements.txt
+++ b/partitioned-heat-conduction/solver-fenicsx/requirements.txt
@@ -1,5 +1,5 @@
numpy >1, <2
-fenicsxprecice
-scipy
-sympy
+fenicsxprecice~=1.0
+scipy>=1.10,<2
+sympy>=1.10,<2
mpi4py>=3
diff --git a/partitioned-heat-conduction/solver-openfoam/.gitignore b/partitioned-heat-conduction/solver-openfoam/.gitignore
deleted file mode 100644
index 1729c7850..000000000
--- a/partitioned-heat-conduction/solver-openfoam/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-Make/*
-!Make/files
-!Make/options
-lnInclude/
diff --git a/partitioned-pipe-multiscale/fluid1d-left-nutils/requirements.txt b/partitioned-pipe-multiscale/fluid1d-left-nutils/requirements.txt
index 758176da0..f4fc6880f 100644
--- a/partitioned-pipe-multiscale/fluid1d-left-nutils/requirements.txt
+++ b/partitioned-pipe-multiscale/fluid1d-left-nutils/requirements.txt
@@ -1,5 +1,5 @@
-setuptools # required by nutils
+setuptools>=69.0.0 # required by nutils
nutils~=9.0
numpy >1, <2
pyprecice~=3.0
-matplotlib
\ No newline at end of file
+matplotlib>=3.5,<4
\ No newline at end of file
diff --git a/partitioned-pipe-multiscale/fluid1d-left-nutils/run.sh b/partitioned-pipe-multiscale/fluid1d-left-nutils/run.sh
index 4e978edf1..4e3e431f5 100755
--- a/partitioned-pipe-multiscale/fluid1d-left-nutils/run.sh
+++ b/partitioned-pipe-multiscale/fluid1d-left-nutils/run.sh
@@ -4,9 +4,15 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-python3 -m venv .venv
-. .venv/bin/activate
-pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
+fi
NUTILS_RICHOUTPUT=no python3 ../solver-fluid1d-nutils/Fluid1D.py side=Left
diff --git a/partitioned-pipe-multiscale/fluid1d-right-nutils/requirements.txt b/partitioned-pipe-multiscale/fluid1d-right-nutils/requirements.txt
index 758176da0..f4fc6880f 100644
--- a/partitioned-pipe-multiscale/fluid1d-right-nutils/requirements.txt
+++ b/partitioned-pipe-multiscale/fluid1d-right-nutils/requirements.txt
@@ -1,5 +1,5 @@
-setuptools # required by nutils
+setuptools>=69.0.0 # required by nutils
nutils~=9.0
numpy >1, <2
pyprecice~=3.0
-matplotlib
\ No newline at end of file
+matplotlib>=3.5,<4
\ No newline at end of file
diff --git a/partitioned-pipe-multiscale/fluid1d-right-nutils/run.sh b/partitioned-pipe-multiscale/fluid1d-right-nutils/run.sh
index e064d1e66..72b0163b1 100755
--- a/partitioned-pipe-multiscale/fluid1d-right-nutils/run.sh
+++ b/partitioned-pipe-multiscale/fluid1d-right-nutils/run.sh
@@ -4,9 +4,15 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-python3 -m venv .venv
-. .venv/bin/activate
-pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
+fi
NUTILS_RICHOUTPUT=no python3 ../solver-fluid1d-nutils/Fluid1D.py side=Right
diff --git a/partitioned-pipe-multiscale/metadata.yaml b/partitioned-pipe-multiscale/metadata.yaml
new file mode 100644
index 000000000..74ba8ae04
--- /dev/null
+++ b/partitioned-pipe-multiscale/metadata.yaml
@@ -0,0 +1,34 @@
+name: Partitioned pipe multiscale
+path: partitioned-pipe-multiscale # relative to git repo
+url: https://precice.org/tutorials-partitioned-pipe-multiscale.html
+
+participants:
+ - Fluid1DLeft
+ # - Fluid1DRight
+ # - Fluid3DLeft
+ - Fluid3DRight
+
+cases:
+ fluid1d-left-nutils:
+ participant: Fluid1DLeft
+ directory: ./fluid1d-left-nutils
+ run: ./run.sh
+ component: nutils-adapter
+
+ # fluid1d-right-nutils:
+ # participant: Fluid1DRight
+ # directory: ./fluid1d-right-nutils
+ # run: ./run.sh
+ # component: nutils-adapter
+
+ # fluid3d-left-openfoam:
+ # participant: Fluid3DLeft
+ # directory: ./fluid3d-left-openfoam
+ # run: ./run.sh
+ # component: openfoam-adapter
+
+ fluid3d-right-openfoam:
+ participant: Fluid3DRight
+ directory: ./fluid3d-right-openfoam
+ run: ./run.sh
+ component: openfoam-adapter
diff --git a/partitioned-pipe-multiscale/precice-config-1d-1d.xml b/partitioned-pipe-multiscale/precice-config-1d-1d.xml
index ca78d8c2e..56b57d57a 100644
--- a/partitioned-pipe-multiscale/precice-config-1d-1d.xml
+++ b/partitioned-pipe-multiscale/precice-config-1d-1d.xml
@@ -32,7 +32,6 @@
from="Fluid1DLeft-Mesh"
to="Fluid1DRight-Mesh"
constraint="consistent" />
-
@@ -45,7 +44,6 @@
from="Fluid1DRight-Mesh"
to="Fluid1DLeft-Mesh"
constraint="consistent" />
-
diff --git a/partitioned-pipe-multiscale/precice-config-1d-3d.xml b/partitioned-pipe-multiscale/precice-config-1d-3d.xml
index 5eef4fe97..2d6230668 100644
--- a/partitioned-pipe-multiscale/precice-config-1d-3d.xml
+++ b/partitioned-pipe-multiscale/precice-config-1d-3d.xml
@@ -37,7 +37,6 @@
from="Fluid3DRight-Mesh"
to="Fluid1DLeft-Mesh"
constraint="consistent" />
-
@@ -56,7 +55,6 @@
from="Fluid1DLeft-Mesh"
to="Fluid3DRight-Mesh"
constraint="consistent" />
-
diff --git a/partitioned-pipe-multiscale/precice-config-3d-1d.xml b/partitioned-pipe-multiscale/precice-config-3d-1d.xml
index addaea07e..8355f165e 100644
--- a/partitioned-pipe-multiscale/precice-config-3d-1d.xml
+++ b/partitioned-pipe-multiscale/precice-config-3d-1d.xml
@@ -37,7 +37,6 @@
from="Fluid3DLeft-Mesh"
to="Fluid1DRight-Mesh"
constraint="consistent" />
-
@@ -56,7 +55,6 @@
from="Fluid1DRight-Mesh"
to="Fluid3DLeft-Mesh"
constraint="consistent" />
-
diff --git a/partitioned-pipe-multiscale/precice-config-3d-3d.xml b/partitioned-pipe-multiscale/precice-config-3d-3d.xml
index a296a8970..0ab5beef5 100644
--- a/partitioned-pipe-multiscale/precice-config-3d-3d.xml
+++ b/partitioned-pipe-multiscale/precice-config-3d-3d.xml
@@ -32,7 +32,6 @@
from="Fluid3DLeft-Mesh"
to="Fluid3DRight-Mesh"
constraint="consistent" />
-
@@ -45,7 +44,6 @@
from="Fluid3DRight-Mesh"
to="Fluid3DLeft-Mesh"
constraint="consistent" />
-
diff --git a/partitioned-pipe-multiscale/reference-results/fluid1d-left-nutils_fluid3d-right-openfoam.tar.gz b/partitioned-pipe-multiscale/reference-results/fluid1d-left-nutils_fluid3d-right-openfoam.tar.gz
new file mode 100644
index 000000000..c61ce8698
--- /dev/null
+++ b/partitioned-pipe-multiscale/reference-results/fluid1d-left-nutils_fluid3d-right-openfoam.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:bc40404e24756a6a6e913356965a67bbe84a1e7596fae90fead5fd4069677deb
+size 18619
diff --git a/partitioned-pipe-multiscale/reference-results/reference_results.metadata b/partitioned-pipe-multiscale/reference-results/reference_results.metadata
new file mode 100644
index 000000000..4442de921
--- /dev/null
+++ b/partitioned-pipe-multiscale/reference-results/reference_results.metadata
@@ -0,0 +1,71 @@
+
+
+# Reference Results
+
+This file contains an overview of the results over the reference results as well as the arguments used to generate them.
+We also include some information on the machine used to generate them
+
+## List of files
+
+| name | time | sha256 |
+|------|------|-------|
+| fluid1d-left-nutils_fluid3d-right-openfoam.tar.gz | 2026-05-28 14:01:56 | bc40404e24756a6a6e913356965a67bbe84a1e7596fae90fead5fd4069677deb |
+
+## List of arguments used to generate the files
+
+| name | value |
+|------|------|
+| PLATFORM | ubuntu_2404 |
+| CALCULIX_VERSION | 2.20 |
+| DUNE_VERSION | 2.9 |
+| DUMUX_VERSION | 3.7 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | 816ffe9 |
+| PRECICE_PRESET | production-audit |
+| PRECICE_UID | 1003 |
+| PRECICE_GID | 1003 |
+## Information about the machine
+
+### uname -a
+
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+
+
+### lscpu
+
+Architecture: x86_64
+CPU op-mode(s): 32-bit, 64-bit
+Address sizes: 45 bits physical, 48 bits virtual
+Byte Order: Little Endian
+CPU(s): 4
+On-line CPU(s) list: 0-3
+Vendor ID: GenuineIntel
+Model name: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz
+CPU family: 6
+Model: 85
+Thread(s) per core: 1
+Core(s) per socket: 1
+Socket(s): 4
+Stepping: 4
+BogoMIPS: 4199.99
+Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat pku ospke md_clear flush_l1d arch_capabilities
+Hypervisor vendor: VMware
+Virtualization type: full
+L1d cache: 128 KiB (4 instances)
+L1i cache: 128 KiB (4 instances)
+L2 cache: 4 MiB (4 instances)
+L3 cache: 88 MiB (4 instances)
+NUMA node(s): 1
+NUMA node0 CPU(s): 0-3
diff --git a/partitioned-pipe-two-phase/metadata.yaml b/partitioned-pipe-two-phase/metadata.yaml
new file mode 100644
index 000000000..03790cd79
--- /dev/null
+++ b/partitioned-pipe-two-phase/metadata.yaml
@@ -0,0 +1,20 @@
+name: Partitioned pipe two phase
+path: partitioned-pipe-two-phase # relative to git repo
+url: https://precice.org/tutorials-partitioned-pipe-two-phase.html
+
+participants:
+ - Fluid1
+ - Fluid2
+
+cases:
+ fluid1-openfoam:
+ participant: Fluid1
+ directory: ./fluid1-openfoam
+ run: ./run.sh
+ component: openfoam-adapter
+
+ fluid2-openfoam:
+ participant: Fluid2
+ directory: ./fluid2-openfoam
+ run: ./run.sh
+ component: openfoam-adapter
diff --git a/partitioned-pipe-two-phase/reference-results/fluid1-openfoam_fluid2-openfoam.tar.gz b/partitioned-pipe-two-phase/reference-results/fluid1-openfoam_fluid2-openfoam.tar.gz
new file mode 100644
index 000000000..01957f955
--- /dev/null
+++ b/partitioned-pipe-two-phase/reference-results/fluid1-openfoam_fluid2-openfoam.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:7e8fc0ad04b413d09909f98cdc070fcb1255833c516f8fc6d8a34c8fa82a2d0b
+size 2508
diff --git a/partitioned-pipe-two-phase/reference-results/reference_results.metadata b/partitioned-pipe-two-phase/reference-results/reference_results.metadata
new file mode 100644
index 000000000..97a7ada77
--- /dev/null
+++ b/partitioned-pipe-two-phase/reference-results/reference_results.metadata
@@ -0,0 +1,71 @@
+
+
+# Reference Results
+
+This file contains an overview of the results over the reference results as well as the arguments used to generate them.
+We also include some information on the machine used to generate them
+
+## List of files
+
+| name | time | sha256 |
+|------|------|-------|
+| fluid1-openfoam_fluid2-openfoam.tar.gz | 2026-05-28 11:46:06 | 7e8fc0ad04b413d09909f98cdc070fcb1255833c516f8fc6d8a34c8fa82a2d0b |
+
+## List of arguments used to generate the files
+
+| name | value |
+|------|------|
+| PLATFORM | ubuntu_2404 |
+| CALCULIX_VERSION | 2.20 |
+| DUNE_VERSION | 2.9 |
+| DUMUX_VERSION | 3.7 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | 9cb7068 |
+| PRECICE_PRESET | production-audit |
+| PRECICE_UID | 1003 |
+| PRECICE_GID | 1003 |
+## Information about the machine
+
+### uname -a
+
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+
+
+### lscpu
+
+Architecture: x86_64
+CPU op-mode(s): 32-bit, 64-bit
+Address sizes: 45 bits physical, 48 bits virtual
+Byte Order: Little Endian
+CPU(s): 4
+On-line CPU(s) list: 0-3
+Vendor ID: GenuineIntel
+Model name: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz
+CPU family: 6
+Model: 85
+Thread(s) per core: 1
+Core(s) per socket: 1
+Socket(s): 4
+Stepping: 4
+BogoMIPS: 4199.99
+Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat pku ospke md_clear flush_l1d arch_capabilities
+Hypervisor vendor: VMware
+Virtualization type: full
+L1d cache: 128 KiB (4 instances)
+L1i cache: 128 KiB (4 instances)
+L2 cache: 4 MiB (4 instances)
+L3 cache: 88 MiB (4 instances)
+NUMA node(s): 1
+NUMA node0 CPU(s): 0-3
diff --git a/partitioned-pipe/README.md b/partitioned-pipe/README.md
index 458a8709a..16a45c11a 100644
--- a/partitioned-pipe/README.md
+++ b/partitioned-pipe/README.md
@@ -27,7 +27,7 @@ Both for Fluid1 and Fluid2, the following participants are available:
* OpenFOAM (pimpleFoam). An incompressible OpenFOAM solver. For more information, have a look at the [OpenFOAM adapter documentation](https://precice.org/adapter-openfoam-overview.html).
-* OpenFOAM (sonicLiquidFoam). A compressible OpenFOAM solver. For more information, have a look at the [OpenFOAM adapter documentation](https://precice.org/adapter-openfoam-overview.html).
+* OpenFOAM (sonicLiquidFoam). A compressible OpenFOAM solver. For more information, have a look at the [OpenFOAM adapter documentation](https://precice.org/adapter-openfoam-overview.html). This setup gives better results if we also couple the pressure gradient. The run scripts enable the respective comments in the `precice-config.xml`.
## Running the Simulation
diff --git a/partitioned-pipe/fluid1-openfoam-sonicliquidfoam/clean.sh b/partitioned-pipe/fluid1-openfoam-sonicliquidfoam/clean.sh
index b64fc5101..06860134e 100755
--- a/partitioned-pipe/fluid1-openfoam-sonicliquidfoam/clean.sh
+++ b/partitioned-pipe/fluid1-openfoam-sonicliquidfoam/clean.sh
@@ -4,3 +4,9 @@ set -e -u
. ../../tools/cleaning-tools.sh
clean_openfoam .
+
+if [ -f ../precice-config.xml.orig ]; then
+ echo "Restoring the precice-config.xml from precice-config.xml.orig"
+ cp -r ../precice-config.xml.orig ../precice-config.xml
+ rm ../precice-config.xml.orig
+fi
\ No newline at end of file
diff --git a/partitioned-pipe/fluid1-openfoam-sonicliquidfoam/run.sh b/partitioned-pipe/fluid1-openfoam-sonicliquidfoam/run.sh
index 8f55fbfa5..86fbb5e22 100755
--- a/partitioned-pipe/fluid1-openfoam-sonicliquidfoam/run.sh
+++ b/partitioned-pipe/fluid1-openfoam-sonicliquidfoam/run.sh
@@ -4,6 +4,15 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
+# The precice-config.xml has the PressureGradient field commented out.
+# That improves the results for the compressible case, so we un-comment it.
+if [ ! -f ../precice-config.xml.orig ]; then
+ echo "Modifying the ../precice-config.xml to enable PressureGradient (see precice-config.xml.orig for the original)"
+ cp -f ../precice-config.xml ../precice-config.xml.orig
+ sed -i "s,,,g" ../precice-config.xml
+fi
+
blockMesh
../../tools/run-openfoam.sh "$@"
diff --git a/partitioned-pipe/fluid2-openfoam-sonicliquidfoam/clean.sh b/partitioned-pipe/fluid2-openfoam-sonicliquidfoam/clean.sh
index b64fc5101..06860134e 100755
--- a/partitioned-pipe/fluid2-openfoam-sonicliquidfoam/clean.sh
+++ b/partitioned-pipe/fluid2-openfoam-sonicliquidfoam/clean.sh
@@ -4,3 +4,9 @@ set -e -u
. ../../tools/cleaning-tools.sh
clean_openfoam .
+
+if [ -f ../precice-config.xml.orig ]; then
+ echo "Restoring the precice-config.xml from precice-config.xml.orig"
+ cp -r ../precice-config.xml.orig ../precice-config.xml
+ rm ../precice-config.xml.orig
+fi
\ No newline at end of file
diff --git a/partitioned-pipe/fluid2-openfoam-sonicliquidfoam/run.sh b/partitioned-pipe/fluid2-openfoam-sonicliquidfoam/run.sh
index 8f55fbfa5..86fbb5e22 100755
--- a/partitioned-pipe/fluid2-openfoam-sonicliquidfoam/run.sh
+++ b/partitioned-pipe/fluid2-openfoam-sonicliquidfoam/run.sh
@@ -4,6 +4,15 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
+# The precice-config.xml has the PressureGradient field commented out.
+# That improves the results for the compressible case, so we un-comment it.
+if [ ! -f ../precice-config.xml.orig ]; then
+ echo "Modifying the ../precice-config.xml to enable PressureGradient (see precice-config.xml.orig for the original)"
+ cp -f ../precice-config.xml ../precice-config.xml.orig
+ sed -i "s,,,g" ../precice-config.xml
+fi
+
blockMesh
../../tools/run-openfoam.sh "$@"
diff --git a/partitioned-pipe/metadata.yaml b/partitioned-pipe/metadata.yaml
new file mode 100644
index 000000000..2b92c351e
--- /dev/null
+++ b/partitioned-pipe/metadata.yaml
@@ -0,0 +1,32 @@
+name: Partitioned pipe
+path: partitioned-pipe # relative to git repo
+url: https://precice.org/tutorials-partitioned-pipe.html
+
+participants:
+ - Fluid1
+ - Fluid2
+
+cases:
+ fluid1-openfoam-pimplefoam:
+ participant: Fluid1
+ directory: ./fluid1-openfoam-pimplefoam
+ run: ./run.sh -parallel
+ component: openfoam-adapter
+
+ fluid1-openfoam-sonicliquidfoam:
+ participant: Fluid1
+ directory: ./fluid1-openfoam-sonicliquidfoam
+ run: ./run.sh -parallel
+ component: openfoam-adapter
+
+ fluid2-openfoam-pimplefoam:
+ participant: Fluid2
+ directory: ./fluid2-openfoam-pimplefoam
+ run: ./run.sh -parallel
+ component: openfoam-adapter
+
+ fluid2-openfoam-sonicliquidfoam:
+ participant: Fluid2
+ directory: ./fluid2-openfoam-sonicliquidfoam
+ run: ./run.sh -parallel
+ component: openfoam-adapter
\ No newline at end of file
diff --git a/partitioned-pipe/reference-results/fluid1-openfoam-pimplefoam_fluid2-openfoam-pimplefoam.tar.gz b/partitioned-pipe/reference-results/fluid1-openfoam-pimplefoam_fluid2-openfoam-pimplefoam.tar.gz
new file mode 100644
index 000000000..5cc6204e0
--- /dev/null
+++ b/partitioned-pipe/reference-results/fluid1-openfoam-pimplefoam_fluid2-openfoam-pimplefoam.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:500166363879b3767f5256dc640d61fa466005e707a45644a7c78a4ea6518132
+size 253022
diff --git a/partitioned-pipe/reference-results/fluid1-openfoam-sonicliquidfoam_fluid2-openfoam-sonicliquidfoam.tar.gz b/partitioned-pipe/reference-results/fluid1-openfoam-sonicliquidfoam_fluid2-openfoam-sonicliquidfoam.tar.gz
new file mode 100644
index 000000000..821630ecb
--- /dev/null
+++ b/partitioned-pipe/reference-results/fluid1-openfoam-sonicliquidfoam_fluid2-openfoam-sonicliquidfoam.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a7aa2d9a4bacc89fe494ee9e812bc5b437957a00943a13faf28887ca4a55fa39
+size 377022
diff --git a/partitioned-pipe/reference-results/reference_results.metadata b/partitioned-pipe/reference-results/reference_results.metadata
new file mode 100644
index 000000000..751c4ae41
--- /dev/null
+++ b/partitioned-pipe/reference-results/reference_results.metadata
@@ -0,0 +1,72 @@
+
+
+# Reference Results
+
+This file contains an overview of the results over the reference results as well as the arguments used to generate them.
+We also include some information on the machine used to generate them
+
+## List of files
+
+| name | time | sha256 |
+|------|------|-------|
+| fluid1-openfoam-pimplefoam_fluid2-openfoam-pimplefoam.tar.gz | 2026-05-28 11:46:06 | 500166363879b3767f5256dc640d61fa466005e707a45644a7c78a4ea6518132 |
+| fluid1-openfoam-sonicliquidfoam_fluid2-openfoam-sonicliquidfoam.tar.gz | 2026-05-28 11:46:06 | a7aa2d9a4bacc89fe494ee9e812bc5b437957a00943a13faf28887ca4a55fa39 |
+
+## List of arguments used to generate the files
+
+| name | value |
+|------|------|
+| PLATFORM | ubuntu_2404 |
+| CALCULIX_VERSION | 2.20 |
+| DUNE_VERSION | 2.9 |
+| DUMUX_VERSION | 3.7 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | 9cb7068 |
+| PRECICE_PRESET | production-audit |
+| PRECICE_UID | 1003 |
+| PRECICE_GID | 1003 |
+## Information about the machine
+
+### uname -a
+
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+
+
+### lscpu
+
+Architecture: x86_64
+CPU op-mode(s): 32-bit, 64-bit
+Address sizes: 45 bits physical, 48 bits virtual
+Byte Order: Little Endian
+CPU(s): 4
+On-line CPU(s) list: 0-3
+Vendor ID: GenuineIntel
+Model name: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz
+CPU family: 6
+Model: 85
+Thread(s) per core: 1
+Core(s) per socket: 1
+Socket(s): 4
+Stepping: 4
+BogoMIPS: 4199.99
+Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat pku ospke md_clear flush_l1d arch_capabilities
+Hypervisor vendor: VMware
+Virtualization type: full
+L1d cache: 128 KiB (4 instances)
+L1i cache: 128 KiB (4 instances)
+L2 cache: 4 MiB (4 instances)
+L3 cache: 88 MiB (4 instances)
+NUMA node(s): 1
+NUMA node0 CPU(s): 0-3
diff --git a/perpendicular-flap-stress/metadata.yaml b/perpendicular-flap-stress/metadata.yaml
new file mode 100644
index 000000000..0c609a703
--- /dev/null
+++ b/perpendicular-flap-stress/metadata.yaml
@@ -0,0 +1,20 @@
+name: Perpendicular flap stress
+path: perpendicular-flap-stress
+url: https://precice.org/tutorials-perpendicular-flap-stress.html
+
+participants:
+ - Fluid
+ - Solid
+
+cases:
+ fluid-openfoam:
+ participant: Fluid
+ directory: ./fluid-openfoam
+ run: ./run.sh
+ component: openfoam-adapter
+
+ # solid-gismo:
+ # participant: Solid
+ # directory: ./solid-gismo
+ # run: ./run.sh
+ # component: gismo-adapter
diff --git a/perpendicular-flap/README.md b/perpendicular-flap/README.md
index e50562681..022150d3a 100644
--- a/perpendicular-flap/README.md
+++ b/perpendicular-flap/README.md
@@ -31,7 +31,7 @@ Fluid participant:
* SU2. As opposed to the other two fluid codes, SU2 is in particular specialized for compressible flow. Therefore the default simulation parameters have been adjusted in order to pull the setup into the compressible flow regime. For more information, have a look at the [SU2 adapter documentation](https://precice.org/adapter-su2-overview.html).
-* Nutils. For more information, have a look at the [Nutils adapter documentation](https://precice.org/adapter-nutils.html). This Nutils solver requires at least Nutils v6.0. This case currently takes orders of magnitude longer than the OpenFOAM and SU2 cases, see [related issue](https://github.com/precice/tutorials/issues/506).
+* Nutils. For more information, have a look at the [Nutils adapter documentation](https://precice.org/adapter-nutils.html). This case currently takes orders of magnitude longer than the OpenFOAM and SU2 cases, see [related issue](https://github.com/precice/tutorials/issues/506).
* Fake. A simple python script that acts as a fake solver and provides an arbitrary force, linearly-increasing per length of the flap. This solver can be used for debugging of the solid participant and its adapter. It also technically works with implicit coupling, thus no changes to the preCICE configuration are necessary. Note that [ASTE's replay mode](https://precice.org/tooling-aste.html#replay-mode) has a similar use case and could also feed artificial or previously recorded real data, replacing an actual solver.
@@ -45,7 +45,7 @@ Solid participant:
* DUNE. For more information, have a look at the [experimental DUNE adapter](https://github.com/precice/dune-adapter) and send us your feedback.
-* Nutils. The structural model is currently limited to linear elasticity. For more information, have a look at the [Nutils adapter documentation](https://precice.org/adapter-nutils.html). This Nutils solver requires at least Nutils v8.0.
+* Nutils. The structural model is currently limited to linear elasticity. For more information, have a look at the [Nutils adapter documentation](https://precice.org/adapter-nutils.html).
* solids4foam. Like for CalculiX, the geometrically non-linear solver is used by default. For more information, see the [solids4foam documentation](https://solids4foam.github.io/documentation/overview.html) and a [related tutorial](https://www.solids4foam.com/tutorials/more-tutorials/fluid-solid-interaction/flexibleOversetCylinder.html). This case works with solids4foam v2.0, which is compatible with up to OpenFOAM v2012 and OpenFOAM 9 (as well as foam-extend, with which the OpenFOAM-preCICE adapter is not compatible), as well as the OpenFOAM-preCICE adapter v1.2.0 or later.
diff --git a/perpendicular-flap/fluid-fake/clean.sh b/perpendicular-flap/fluid-fake/clean.sh
new file mode 100755
index 000000000..8d5d37784
--- /dev/null
+++ b/perpendicular-flap/fluid-fake/clean.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env sh
+set -e -u
+
+. ../../tools/cleaning-tools.sh
+
+rm -rvf ./output/*.vtk
+clean_precice_logs .
+clean_case_logs .
diff --git a/perpendicular-flap/fluid-fake/run.sh b/perpendicular-flap/fluid-fake/run.sh
index cae9e3b83..3d09d256a 100755
--- a/perpendicular-flap/fluid-fake/run.sh
+++ b/perpendicular-flap/fluid-fake/run.sh
@@ -1,10 +1,18 @@
#!/usr/bin/env bash
set -e -u
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+. ../../tools/log.sh
+exec > >(tee --append "$LOGFILE") 2>&1
+
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
python3 fake.py
+
+close_log
\ No newline at end of file
diff --git a/perpendicular-flap/fluid-nutils/requirements.txt b/perpendicular-flap/fluid-nutils/requirements.txt
index b81f4ff8f..ecf10833d 100644
--- a/perpendicular-flap/fluid-nutils/requirements.txt
+++ b/perpendicular-flap/fluid-nutils/requirements.txt
@@ -1,4 +1,4 @@
-setuptools # required by nutils
+setuptools>=69.0.0 # required by nutils
nutils~=6.0
numpy >1, <2
pyprecice~=3.0
diff --git a/perpendicular-flap/fluid-nutils/run.sh b/perpendicular-flap/fluid-nutils/run.sh
index f68b56661..9d67e978a 100755
--- a/perpendicular-flap/fluid-nutils/run.sh
+++ b/perpendicular-flap/fluid-nutils/run.sh
@@ -4,11 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
python3 fluid.py
diff --git a/perpendicular-flap/fluid-su2/run.sh b/perpendicular-flap/fluid-su2/run.sh
index e6c7a0fcb..93f800d97 100755
--- a/perpendicular-flap/fluid-su2/run.sh
+++ b/perpendicular-flap/fluid-su2/run.sh
@@ -4,11 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv --system-site-packages .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv --system-site-packages .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
SU2_preCICE_FSI.py -f euler_config_unsteady.cfg --parallel
diff --git a/perpendicular-flap/metadata.yaml b/perpendicular-flap/metadata.yaml
index 78d8acef9..0cacb742e 100644
--- a/perpendicular-flap/metadata.yaml
+++ b/perpendicular-flap/metadata.yaml
@@ -7,6 +7,12 @@ participants:
- Solid
cases:
+ fluid-fake:
+ participant: Fluid
+ directory: ./fluid-fake
+ run: ./run.sh
+ component: bare
+
fluid-nutils:
participant: Fluid
directory: ./fluid-nutils
@@ -16,7 +22,7 @@ cases:
fluid-openfoam:
participant: Fluid
directory: ./fluid-openfoam
- run: ./run.sh
+ run: ./run.sh
component: openfoam-adapter
fluid-su2:
@@ -42,13 +48,25 @@ cases:
# directory: ./solid-dune
# run: ./run.sh
# component: dune-adapter
-
+
+ solid-fake:
+ participant: Solid
+ directory: ./solid-fake
+ run: ./run.sh
+ component: bare
+
solid-fenics:
participant: Solid
directory: ./solid-fenics
run: ./run.sh
component: fenics-adapter
-
+
+ solid-nutils:
+ participant: Solid
+ directory: ./solid-nutils
+ run: ./run.sh
+ component: nutils-adapter
+
solid-openfoam:
participant: Solid
directory: ./solid-openfoam
@@ -60,5 +78,3 @@ cases:
# directory: ./solid-solids4foam
# run: ./run.sh
# component: openfoam-adapter
-
-
diff --git a/perpendicular-flap/reference-results/fluid-fake_solid-fake.tar.gz b/perpendicular-flap/reference-results/fluid-fake_solid-fake.tar.gz
new file mode 100644
index 000000000..851131750
--- /dev/null
+++ b/perpendicular-flap/reference-results/fluid-fake_solid-fake.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:292e859f538422389088f694de66988a5550d1700fe5881e4a8f0c2e349f7647
+size 17340
diff --git a/perpendicular-flap/reference-results/fluid-nutils_solid-calculix.tar.gz b/perpendicular-flap/reference-results/fluid-nutils_solid-calculix.tar.gz
new file mode 100644
index 000000000..9863c0e95
--- /dev/null
+++ b/perpendicular-flap/reference-results/fluid-nutils_solid-calculix.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:19316047524c56e1675cae8e80014bc6f845f074ce8b225b880fa7a7e140e567
+size 103799
diff --git a/perpendicular-flap/reference-results/fluid-openfoam_solid-calculix.tar.gz b/perpendicular-flap/reference-results/fluid-openfoam_solid-calculix.tar.gz
index 7f7181740..f03c95539 100644
--- a/perpendicular-flap/reference-results/fluid-openfoam_solid-calculix.tar.gz
+++ b/perpendicular-flap/reference-results/fluid-openfoam_solid-calculix.tar.gz
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:4fbb2c688033023cda1ff26f7c97bb123931014d66620b572c930e4b8e0bcf7f
-size 13543772
+oid sha256:1d8b37c6aa705766f5a9013381a044cc825b807bfcfc06b26adaea88c4de8afb
+size 4769628
diff --git a/perpendicular-flap/reference-results/fluid-openfoam_solid-dealii.tar.gz b/perpendicular-flap/reference-results/fluid-openfoam_solid-dealii.tar.gz
index f10fe7a96..e377f47c8 100644
--- a/perpendicular-flap/reference-results/fluid-openfoam_solid-dealii.tar.gz
+++ b/perpendicular-flap/reference-results/fluid-openfoam_solid-dealii.tar.gz
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:6fdbfbdf4636e3d646cb74741fcd986a025ae1a07462b2cd321d3da46e95d2f0
-size 7892633
+oid sha256:562d713526dcd4d2daaa10b92fc09d01fcae88017d0d50b7dd78394c661410f9
+size 3167756
diff --git a/perpendicular-flap/reference-results/fluid-openfoam_solid-fenics.tar.gz b/perpendicular-flap/reference-results/fluid-openfoam_solid-fenics.tar.gz
index f9aacc6c6..53d0c3580 100644
--- a/perpendicular-flap/reference-results/fluid-openfoam_solid-fenics.tar.gz
+++ b/perpendicular-flap/reference-results/fluid-openfoam_solid-fenics.tar.gz
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:49cd8553f6ce718a23c8b727ffbb0b1e4c45b2286ecb071120ff9327b1ebf751
-size 3396348
+oid sha256:002d647077d0f4558bdf692c858a12d8078bf460dbb336bdba22389f8f54eac9
+size 31275
diff --git a/perpendicular-flap/reference-results/fluid-openfoam_solid-nutils.tar.gz b/perpendicular-flap/reference-results/fluid-openfoam_solid-nutils.tar.gz
new file mode 100644
index 000000000..f775666ef
--- /dev/null
+++ b/perpendicular-flap/reference-results/fluid-openfoam_solid-nutils.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d8b622b7fa5a6b56dcdbfa09f077d78a38ae565fa2e4e9d286fc08d1de985a1e
+size 56534
diff --git a/perpendicular-flap/reference-results/fluid-openfoam_solid-openfoam.tar.gz b/perpendicular-flap/reference-results/fluid-openfoam_solid-openfoam.tar.gz
index 610232565..ed3b5dc3b 100644
--- a/perpendicular-flap/reference-results/fluid-openfoam_solid-openfoam.tar.gz
+++ b/perpendicular-flap/reference-results/fluid-openfoam_solid-openfoam.tar.gz
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:e138d80b4640eac657ba3e03ac54391f92381b3555150887129fce6f6321facd
-size 2368325
+oid sha256:347c9e1a521146c2855f17798edd9ca2aa1ed8e24b2f1412655c8260d860a96a
+size 4532
diff --git a/perpendicular-flap/reference-results/fluid-openfoam_solid-upstream-dealii_solid-downstream-dealii.tar.gz b/perpendicular-flap/reference-results/fluid-openfoam_solid-upstream-dealii_solid-downstream-dealii.tar.gz
index 2148af4e3..65894323c 100644
--- a/perpendicular-flap/reference-results/fluid-openfoam_solid-upstream-dealii_solid-downstream-dealii.tar.gz
+++ b/perpendicular-flap/reference-results/fluid-openfoam_solid-upstream-dealii_solid-downstream-dealii.tar.gz
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:ea2d5946f64667ba05ab3a3516cca7c3af3a59374ff22d0a69e0098c00c1ace1
-size 11725074
+oid sha256:d4bfc7abd3e14ae860d676d426acefc2d998bcbbb2ce79a189cadfc2aa7d3a65
+size 4892505
diff --git a/perpendicular-flap/reference-results/fluid-su2_solid-fenics.tar.gz b/perpendicular-flap/reference-results/fluid-su2_solid-fenics.tar.gz
index b66c8f2c2..1e2c6c5a4 100644
--- a/perpendicular-flap/reference-results/fluid-su2_solid-fenics.tar.gz
+++ b/perpendicular-flap/reference-results/fluid-su2_solid-fenics.tar.gz
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8c41e5f1390b4b7038abf42e874438603efb0fa032a3f5f249c5475214cafcde
-size 3410840
+oid sha256:6f77d1458d64b243af525c09d62cfa7da217d6ea5d0924a769c73ef50e500757
+size 32181
diff --git a/perpendicular-flap/reference-results/reference_results.metadata b/perpendicular-flap/reference-results/reference_results.metadata
index 10c898c8c..9e8b4aff6 100644
--- a/perpendicular-flap/reference-results/reference_results.metadata
+++ b/perpendicular-flap/reference-results/reference_results.metadata
@@ -11,40 +11,37 @@ We also include some information on the machine used to generate them
| name | time | sha256 |
|------|------|-------|
-| fluid-openfoam_solid-calculix.tar.gz | 2026-05-11 07:45:27 | 4fbb2c688033023cda1ff26f7c97bb123931014d66620b572c930e4b8e0bcf7f |
-| fluid-openfoam_solid-openfoam.tar.gz | 2026-05-11 07:45:27 | e138d80b4640eac657ba3e03ac54391f92381b3555150887129fce6f6321facd |
-| fluid-su2_solid-fenics.tar.gz | 2026-05-11 07:45:27 | 8c41e5f1390b4b7038abf42e874438603efb0fa032a3f5f249c5475214cafcde |
-| fluid-openfoam_solid-fenics.tar.gz | 2026-05-11 07:45:27 | 49cd8553f6ce718a23c8b727ffbb0b1e4c45b2286ecb071120ff9327b1ebf751 |
-| fluid-openfoam_solid-dealii.tar.gz | 2026-05-11 07:45:27 | 6fdbfbdf4636e3d646cb74741fcd986a025ae1a07462b2cd321d3da46e95d2f0 |
+| fluid-openfoam_solid-nutils.tar.gz | 2026-05-31 00:45:02 | d8b622b7fa5a6b56dcdbfa09f077d78a38ae565fa2e4e9d286fc08d1de985a1e |
+| fluid-fake_solid-fake.tar.gz | 2026-05-31 00:45:02 | 292e859f538422389088f694de66988a5550d1700fe5881e4a8f0c2e349f7647 |
## List of arguments used to generate the files
| name | value |
|------|------|
-| PRECICE_REF | d199bb3 |
-| PRECICE_PRESET | production-audit |
-| OPENFOAM_EXECUTABLE | openfoam2312 |
-| OPENFOAM_ADAPTER_REF | v1.3.1 |
-| PYTHON_BINDINGS_REF | v3.2.0 |
-| FENICS_ADAPTER_REF | v2.2.0 |
-| TUTORIALS_REF | b18b3ef |
| PLATFORM | ubuntu_2404 |
| CALCULIX_VERSION | 2.20 |
-| CALCULIX_ADAPTER_REF | v2.20.1 |
-| SU2_VERSION | 7.5.1 |
-| SU2_ADAPTER_REF | 64d4aff |
-| DEALII_ADAPTER_REF | 02c5d18 |
| DUNE_VERSION | 2.9 |
| DUMUX_VERSION | 3.7 |
-| DUMUX_ADAPTER_REF | 0e914bb |
-| MICRO_MANAGER_REF | v0.8.0 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | more-tests |
+| PRECICE_PRESET | production-audit |
| PRECICE_UID | 1003 |
| PRECICE_GID | 1003 |
## Information about the machine
### uname -a
-Linux precice-tests 5.15.0-177-generic #187-Ubuntu SMP Sat Apr 11 22:54:33 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
### lscpu
diff --git a/perpendicular-flap/solid-fake/clean.sh b/perpendicular-flap/solid-fake/clean.sh
new file mode 100755
index 000000000..8d5d37784
--- /dev/null
+++ b/perpendicular-flap/solid-fake/clean.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env sh
+set -e -u
+
+. ../../tools/cleaning-tools.sh
+
+rm -rvf ./output/*.vtk
+clean_precice_logs .
+clean_case_logs .
diff --git a/perpendicular-flap/solid-fake/run.sh b/perpendicular-flap/solid-fake/run.sh
index cae9e3b83..2739404f2 100755
--- a/perpendicular-flap/solid-fake/run.sh
+++ b/perpendicular-flap/solid-fake/run.sh
@@ -1,10 +1,18 @@
#!/usr/bin/env bash
set -e -u
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+. ../../tools/log.sh
+exec > >(tee --append "$LOGFILE") 2>&1
+
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
python3 fake.py
+
+close_log
diff --git a/perpendicular-flap/solid-fenics/requirements.txt b/perpendicular-flap/solid-fenics/requirements.txt
index 1b61f98a2..55f045e6c 100644
--- a/perpendicular-flap/solid-fenics/requirements.txt
+++ b/perpendicular-flap/solid-fenics/requirements.txt
@@ -1,6 +1,6 @@
fenicsprecice~=2.2
numpy >1, <2
-matplotlib
+matplotlib>=3.5,<4
# Assuming FEniCS from ppa:fenics-packages/fenics was installed https://fenicsproject.org/download/archive/
# Use --system-site-packages in venv
diff --git a/perpendicular-flap/solid-fenics/run.sh b/perpendicular-flap/solid-fenics/run.sh
index 310a8fb12..1d0d38150 100755
--- a/perpendicular-flap/solid-fenics/run.sh
+++ b/perpendicular-flap/solid-fenics/run.sh
@@ -4,11 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv --system-site-packages .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv --system-site-packages .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
python3 solid.py
diff --git a/perpendicular-flap/solid-nutils/requirements.txt b/perpendicular-flap/solid-nutils/requirements.txt
index 8ae441ba1..cfcb0a3ae 100644
--- a/perpendicular-flap/solid-nutils/requirements.txt
+++ b/perpendicular-flap/solid-nutils/requirements.txt
@@ -1,4 +1,4 @@
-setuptools # required by nutils
+setuptools>=69.0.0 # required by nutils
nutils>=8.5
numpy >1, <2
pyprecice~=3.0
diff --git a/perpendicular-flap/solid-nutils/run.sh b/perpendicular-flap/solid-nutils/run.sh
index 1b0420d63..83e7257b8 100755
--- a/perpendicular-flap/solid-nutils/run.sh
+++ b/perpendicular-flap/solid-nutils/run.sh
@@ -4,11 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
python3 solid.py richoutput=no
diff --git a/perpendicular-flap/solid-openfoam/solidDisplacementFoamForce/.gitignore b/perpendicular-flap/solid-openfoam/solidDisplacementFoamForce/.gitignore
deleted file mode 100644
index 1729c7850..000000000
--- a/perpendicular-flap/solid-openfoam/solidDisplacementFoamForce/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-Make/*
-!Make/files
-!Make/options
-lnInclude/
diff --git a/quickstart/README.md b/quickstart/README.md
index b3561e0a7..1d4d418de 100644
--- a/quickstart/README.md
+++ b/quickstart/README.md
@@ -29,13 +29,13 @@ For this tutorial, we will mainly need to install preCICE, OpenFOAM, and the Ope
sudo apt install ./libprecice3_3.4.1_resolute.deb
```
- | OS | Package |
- | --- | --- |
- | Ubuntu 22.04 Jammy Jellyfish | [`libprecice3_3.4.1_jammy.deb`](https://github.com/precice/precice/releases/download/v3.4.1/libprecice3_3.4.1_jammy.deb) |
- | Ubuntu 24.04 Noble Numbat | [`libprecice3_3.4.1_noble.deb`](https://github.com/precice/precice/releases/download/v3.4.1/libprecice3_3.4.1_noble.deb) |
+ | OS | Package |
+ | --- | --- |
+ | Ubuntu 22.04 Jammy Jellyfish | [`libprecice3_3.4.1_jammy.deb`](https://github.com/precice/precice/releases/download/v3.4.1/libprecice3_3.4.1_jammy.deb) |
+ | Ubuntu 24.04 Noble Numbat | [`libprecice3_3.4.1_noble.deb`](https://github.com/precice/precice/releases/download/v3.4.1/libprecice3_3.4.1_noble.deb) |
| Ubuntu 26.04 Resolute Raccoon | [`libprecice3_3.4.1_resolute.deb`](https://github.com/precice/precice/releases/download/v3.4.1/libprecice3_3.4.1_resolute.deb) |
- | Debian 13 Trixie | [`libprecice3_3.4.1_trixie.deb`](https://github.com/precice/precice/releases/download/v3.4.1/libprecice3_3.4.1_trixie.deb) |
- | Something else | See an [overview of options](https://precice.org/installation-overview.html) |
+ | Debian 13 Trixie | [`libprecice3_3.4.1_trixie.deb`](https://github.com/precice/precice/releases/download/v3.4.1/libprecice3_3.4.1_trixie.deb) |
+ | Something else | See an [overview of options](https://precice.org/installation-overview.html) |
Facing any problems? [Ask for help](https://precice.org/community-channels.html).
2. We will use OpenFOAM here and in many of our tutorial cases, so [install OpenFOAM](https://precice.org/adapter-openfoam-support.html):
@@ -120,6 +120,12 @@ You can also run OpenFOAM in parallel: `./run.sh -parallel`.
In serial, the simulation should take less than a minute to compute (simulated time: 2.5s).
+{% note %}
+While we recommend starting with the latest OpenFOAM version from openfoam.com,
+this case can alternatively be executed with foam-extend.
+For that, replace `run-openfoam.sh` with `run-foam-extend.sh` in the `run.sh` script.
+{% endnote %}
+
## Visualizing the results
You can visualize the simulation results of the `Fluid` participant using ParaView and loading the (empty) file `fluid-openfoam/fluid-openfoam.foam`. The rigid body does not generate any readable output files, but the OpenFOAM data should be enough for now: click "play" in ParaView, the flap should already be moving! 🎉
diff --git a/quickstart/fluid-openfoam/0/U b/quickstart/fluid-openfoam/0/U
index ebf7eb904..7d1ead131 100644
--- a/quickstart/fluid-openfoam/0/U
+++ b/quickstart/fluid-openfoam/0/U
@@ -22,11 +22,14 @@ boundaryField
top
{
type noSlip;
+ value uniform (0 0 0);
+ // Note: Values in noSlip are only needed for foam-extend
}
bottom
{
type noSlip;
+ value uniform (0 0 0);
}
inlet
diff --git a/quickstart/fluid-openfoam/constant/dynamicMeshDict b/quickstart/fluid-openfoam/constant/dynamicMeshDict
index ec8a77f10..446748859 100644
--- a/quickstart/fluid-openfoam/constant/dynamicMeshDict
+++ b/quickstart/fluid-openfoam/constant/dynamicMeshDict
@@ -14,6 +14,11 @@ motionSolverLibs ("libfvMotionSolvers.so");
solver displacementLaplacian;
// OpenFOAM9 or newer: rename "solver" to "motionSolver"
+// The following entries are only relevant to foam-extend
+/* uncomment
+diffusivity uniform;
+*/ // foam-extend
+
displacementLaplacianCoeffs {
diffusivity quadratic inverseDistance (flap);
}
diff --git a/quickstart/fluid-openfoam/system/controlDict b/quickstart/fluid-openfoam/system/controlDict
index a527b5781..298e9843b 100644
--- a/quickstart/fluid-openfoam/system/controlDict
+++ b/quickstart/fluid-openfoam/system/controlDict
@@ -3,13 +3,17 @@ FoamFile
version 2.0;
format ascii;
class dictionary;
+ location "system";
object controlDict;
}
+// Note: This file is prepared to run with the latest supported version of OpenFOAM.com.
+// The tutorials/tools/run-foam-extend.sh script can modify this and other files to run with foam-extend.
+// The format of the file (e.g., linked libraries in one line each) is at parts important to the script.
+
application pimpleFoam; // latest OpenFOAM
// application pimpleDyMFoam; // OpenFOAM v1712, OpenFOAM 5.x, or older
-
startFrom startTime;
startTime 0;
@@ -36,7 +40,10 @@ timeFormat general;
timePrecision 8;
-libs ("libpreciceAdapterFunctionObject.so");
+libs
+(
+ "libpreciceAdapterFunctionObject.so"
+);
functions
{
forces
@@ -47,6 +54,15 @@ functions
rho rhoInf;
log true;
rhoInf 10;
+ // The following entries are only relevant to foam-extend
+ /* uncomment
+ functionObjectLibs ( "libforces.so" );
+ outputControl timeStep;
+ outputInterval 1;
+ pName p;
+ UName U;
+ rhoName rhoInf;
+ */ // foam-extend
CofR (0 0 0);
}
diff --git a/quickstart/fluid-openfoam/system/fvSchemes b/quickstart/fluid-openfoam/system/fvSchemes
index 2035cd05c..94242e0f7 100644
--- a/quickstart/fluid-openfoam/system/fvSchemes
+++ b/quickstart/fluid-openfoam/system/fvSchemes
@@ -21,6 +21,10 @@ divSchemes
{
default none;
div(phi,U) Gauss linearUpwind grad(U);
+ // The following entries are only relevant to foam-extend
+ /* uncomment
+ div((nuEff*dev(T(grad(U))))) Gauss linear;
+ */ // foam-extend
div((nuEff*dev2(T(grad(U))))) Gauss linear;
}
diff --git a/quickstart/fluid-openfoam/system/fvSolution b/quickstart/fluid-openfoam/system/fvSolution
index 813288c04..7b7785df5 100644
--- a/quickstart/fluid-openfoam/system/fvSolution
+++ b/quickstart/fluid-openfoam/system/fvSolution
@@ -14,6 +14,12 @@ solvers
tolerance 1e-6;
relTol 1e-4;
smoother DICGaussSeidel;
+ // The following entries are only relevant to foam-extend
+ /* uncomment
+ agglomerator faceAreaPair;
+ nCellsInCoarsestLevel 10;
+ mergeLevels 1;
+ */ // foam-extend
}
pFinal
@@ -78,3 +84,18 @@ potentialFlow
{
nNonOrthogonalCorrectors 1;
}
+
+// The following entries are only relevant to foam-extend
+/* uncomment
+relaxationFactors
+{
+ U 0.7;
+ UFinal 1;
+}
+
+fieldBounds
+{
+ p -1e5 1e5;
+ U 100;
+}
+*/ // foam-extend
diff --git a/quickstart/fluid-openfoam/system/preciceDict b/quickstart/fluid-openfoam/system/preciceDict
index c67f623a0..69e4bfdcc 100644
--- a/quickstart/fluid-openfoam/system/preciceDict
+++ b/quickstart/fluid-openfoam/system/preciceDict
@@ -36,4 +36,5 @@ interfaces
FSI
{
rho rho [1 -3 0 0 0 0 0] 1000;
+ nu nu [0 2 -1 0 0 0 0] 0.001; // Only relevant to foam-extend
}
diff --git a/quickstart/reference-results/fluid-openfoam_solid-cpp.tar.gz b/quickstart/reference-results/fluid-openfoam_solid-cpp.tar.gz
index cb8869345..ca9630071 100644
--- a/quickstart/reference-results/fluid-openfoam_solid-cpp.tar.gz
+++ b/quickstart/reference-results/fluid-openfoam_solid-cpp.tar.gz
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:59f89f37b1378dc850bd00260a495b3b4133c5034c84dab46daddc718f8c2d53
-size 473043
+oid sha256:1e3357da0f3683de0d3433504197b1471d585a3d31d0f6da8caed416ec08558b
+size 198911
diff --git a/quickstart/reference-results/reference_results.metadata b/quickstart/reference-results/reference_results.metadata
index 1d658214a..54578177b 100644
--- a/quickstart/reference-results/reference_results.metadata
+++ b/quickstart/reference-results/reference_results.metadata
@@ -11,36 +11,36 @@ We also include some information on the machine used to generate them
| name | time | sha256 |
|------|------|-------|
-| fluid-openfoam_solid-cpp.tar.gz | 2026-05-11 07:45:27 | 59f89f37b1378dc850bd00260a495b3b4133c5034c84dab46daddc718f8c2d53 |
+| fluid-openfoam_solid-cpp.tar.gz | 2026-05-28 11:46:06 | 1e3357da0f3683de0d3433504197b1471d585a3d31d0f6da8caed416ec08558b |
## List of arguments used to generate the files
| name | value |
|------|------|
-| PRECICE_REF | d199bb3 |
-| PRECICE_PRESET | production-audit |
-| OPENFOAM_EXECUTABLE | openfoam2312 |
-| OPENFOAM_ADAPTER_REF | v1.3.1 |
-| PYTHON_BINDINGS_REF | v3.2.0 |
-| FENICS_ADAPTER_REF | v2.2.0 |
-| TUTORIALS_REF | b18b3ef |
| PLATFORM | ubuntu_2404 |
| CALCULIX_VERSION | 2.20 |
-| CALCULIX_ADAPTER_REF | v2.20.1 |
-| SU2_VERSION | 7.5.1 |
-| SU2_ADAPTER_REF | 64d4aff |
-| DEALII_ADAPTER_REF | 02c5d18 |
| DUNE_VERSION | 2.9 |
| DUMUX_VERSION | 3.7 |
-| DUMUX_ADAPTER_REF | 0e914bb |
-| MICRO_MANAGER_REF | v0.8.0 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | 9cb7068 |
+| PRECICE_PRESET | production-audit |
| PRECICE_UID | 1003 |
| PRECICE_GID | 1003 |
## Information about the machine
### uname -a
-Linux precice-tests 5.15.0-177-generic #187-Ubuntu SMP Sat Apr 11 22:54:33 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
### lscpu
diff --git a/quickstart/solid-cpp/.gitignore b/quickstart/solid-cpp/.gitignore
index 01e69efeb..21e96cc46 100644
--- a/quickstart/solid-cpp/.gitignore
+++ b/quickstart/solid-cpp/.gitignore
@@ -1,5 +1 @@
-CMakeFiles/
-cmake_install.cmake
-CMakeCache.txt
-Makefile
rigid_body_solver
diff --git a/requirements-reference.txt b/requirements-reference.txt
new file mode 100644
index 000000000..336056808
--- /dev/null
+++ b/requirements-reference.txt
@@ -0,0 +1,320 @@
+# Pinned Python dependency versions for preCICE tutorial distributions.
+# Reference manifest only: tutorial run scripts keep using loose requirements.txt constraints.
+# Generated by tools/report_tutorial_requirements.py — do not edit manually.
+# Generated: 2026-06-16T21:08:47Z
+
+# channel-transport/fluid-nutils/requirements.txt
+setuptools==82.0.1
+nutils==7.3
+numpy==1.26.4
+pyprecice==3.4.0
+setuptools==82.0.1
+
+# channel-transport/transport-nutils/requirements.txt
+setuptools==82.0.1
+nutils==7.3
+numpy==1.26.4
+pyprecice @ git+https://github.com/precice/python-bindings.git@develop
+setuptools==82.0.1
+
+# channel-transport-particles/fluid-nutils/requirements.txt
+setuptools==82.0.1
+nutils==7.3
+numpy==1.26.4
+pyprecice==3.4.0
+setuptools==82.0.1
+
+# channel-transport-reaction/chemical-fenics/requirements.txt
+numpy==1.26.4
+fenicsprecice==2.3.0
+fenics-dijitso==2019.1.0
+fenics-dolfin~=2019.0 # unresolved (not on PyPI or no matching version)
+fenics-ffc==2019.1.0.post0
+fenics-fiat==2019.1.0
+fenics-ufl-legacy==2022.3.0
+
+# channel-transport-reaction/fluid-fenics/requirements.txt
+numpy==1.26.4
+fenicsprecice==2.3.0
+fenics-dijitso==2019.1.0
+fenics-dolfin~=2019.0 # unresolved (not on PyPI or no matching version)
+fenics-ffc==2019.1.0.post0
+fenics-fiat==2019.1.0
+fenics-ufl-legacy==2022.3.0
+
+# elastic-tube-1d/fluid-python/requirements.txt
+matplotlib==3.11.0
+numpy==1.26.4
+pyprecice==3.4.0
+
+# elastic-tube-1d/solid-python/requirements.txt
+numpy==1.26.4
+pyprecice==3.4.0
+
+# elastic-tube-3d/solid-fenics/requirements.txt
+fenicsprecice==2.3.0
+numpy==1.26.4
+fenics-dijitso==2019.1.0
+fenics-dolfin~=2019.0 # unresolved (not on PyPI or no matching version)
+fenics-ffc==2019.1.0.post0
+fenics-fiat==2019.1.0
+fenics-ufl-legacy==2022.3.0
+
+# flow-around-controlled-moving-cylinder/controller-fmi/requirements.txt
+fmiprecice==0.2.1
+
+# flow-around-controlled-moving-cylinder/solid-python/requirements.txt
+pyprecice==3.4.0
+numpy==1.26.4
+
+# flow-over-heated-plate/fluid-su2/requirements.txt
+numpy==1.26.4
+pyprecice==3.4.0
+
+# flow-over-heated-plate/solid-dunefem/requirements.txt
+dune-fem==2.12.0.2
+pyprecice==3.4.0
+
+# flow-over-heated-plate/solid-fenics/requirements.txt
+fenicsprecice==2.3.0
+numpy==1.26.4
+fenics-dijitso==2019.1.0
+fenics-dolfin~=2019.0 # unresolved (not on PyPI or no matching version)
+fenics-ffc==2019.1.0.post0
+fenics-fiat==2019.1.0
+fenics-ufl-legacy==2022.3.0
+
+# flow-over-heated-plate/solid-fenicsx/requirements.txt
+numpy==1.26.4
+fenicsxprecice==1.0.1
+mpi4py==4.1.2
+
+# flow-over-heated-plate/solid-nutils/requirements.txt
+setuptools==82.0.1
+nutils==7.3
+numpy==1.26.4
+pyprecice==3.4.0
+
+# oscillator/mass-left-fmi/requirements.txt
+fmiprecice==0.2.1
+pandas==2.3.3
+
+# oscillator/mass-right-fmi/requirements.txt
+fmiprecice==0.2.1
+pandas==2.3.3
+
+# oscillator/solver-fmi/requirements.txt
+fmiprecice==0.2.1
+pandas==2.3.3
+
+# oscillator/solver-python/requirements.txt
+numpy==1.26.4
+pyprecice==3.4.0
+scipy==1.17.1
+
+# oscillator-overlap/solver-python/requirements.txt
+numpy==1.26.4
+pyprecice==3.4.0
+scipy==1.17.1
+
+# partitioned-heat-conduction/dirichlet-nutils/requirements.txt
+setuptools==82.0.1
+nutils==7.3
+numpy==1.26.4
+pyprecice==3.4.0
+
+# partitioned-heat-conduction/neumann-nutils/requirements.txt
+setuptools==82.0.1
+nutils==7.3
+numpy==1.26.4
+pyprecice==3.4.0
+
+# partitioned-heat-conduction/solver-fenics/requirements.txt
+numpy==1.26.4
+fenicsprecice==2.3.0
+scipy==1.17.1
+fenics-dijitso==2019.1.0
+fenics-dolfin~=2019.0 # unresolved (not on PyPI or no matching version)
+fenics-ffc==2019.1.0.post0
+fenics-fiat==2019.1.0
+fenics-ufl-legacy==2022.3.0
+
+# partitioned-heat-conduction/solver-fenicsx/requirements.txt
+numpy==1.26.4
+fenicsxprecice==1.0.1
+scipy==1.17.1
+sympy==1.14.0
+mpi4py==4.1.2
+
+# partitioned-heat-conduction-3d/solver-fenicsx/requirements.txt
+numpy==1.26.4
+fenicsxprecice==1.0.1
+scipy==1.17.1
+sympy==1.14.0
+gmsh==4.15.2
+
+# partitioned-heat-conduction-complex/solver-fenics/requirements.txt
+fenicsprecice==2.3.0
+numpy==1.26.4
+sympy==1.14.0
+fenics-dijitso==2019.1.0
+fenics-dolfin~=2019.0 # unresolved (not on PyPI or no matching version)
+fenics-ffc==2019.1.0.post0
+fenics-fiat==2019.1.0
+fenics-ufl-legacy==2022.3.0
+
+# partitioned-heat-conduction-direct/dirichlet-nutils/requirements.txt
+setuptools==82.0.1
+nutils==7.3
+numpy==1.26.4
+pyprecice==3.4.0
+
+# partitioned-heat-conduction-direct/neumann-nutils/requirements.txt
+setuptools==82.0.1
+nutils==7.3
+numpy==1.26.4
+pyprecice==3.4.0
+
+# partitioned-heat-conduction-overlap/solver-fenics/requirements.txt
+fenicsprecice==2.3.0
+numpy==1.26.4
+fenics-dijitso==2019.1.0
+fenics-dolfin~=2019.0 # unresolved (not on PyPI or no matching version)
+fenics-ffc==2019.1.0.post0
+fenics-fiat==2019.1.0
+fenics-ufl-legacy==2022.3.0
+
+# partitioned-pipe-multiscale/fluid1d-left-nutils/requirements.txt
+setuptools==82.0.1
+nutils==9.2
+numpy==1.26.4
+pyprecice==3.4.0
+matplotlib==3.11.0
+
+# partitioned-pipe-multiscale/fluid1d-right-nutils/requirements.txt
+setuptools==82.0.1
+nutils==9.2
+numpy==1.26.4
+pyprecice==3.4.0
+matplotlib==3.11.0
+
+# perpendicular-flap/fluid-fake/requirements.txt
+numpy==1.26.4
+pyprecice==3.4.0
+
+# perpendicular-flap/fluid-nutils/requirements.txt
+setuptools==82.0.1
+nutils==6.3
+numpy==1.26.4
+pyprecice==3.4.0
+treelog==1.0
+
+# perpendicular-flap/fluid-su2/requirements.txt
+numpy==1.26.4
+pyprecice==3.4.0
+
+# perpendicular-flap/solid-fake/requirements.txt
+numpy==1.26.4
+pyprecice==3.4.0
+
+# perpendicular-flap/solid-fenics/requirements.txt
+fenicsprecice==2.3.0
+numpy==1.26.4
+matplotlib==3.11.0
+fenics-dijitso==2019.1.0
+fenics-dolfin~=2019.0 # unresolved (not on PyPI or no matching version)
+fenics-ffc==2019.1.0.post0
+fenics-fiat==2019.1.0
+fenics-ufl-legacy==2022.3.0
+
+# perpendicular-flap/solid-nutils/requirements.txt
+setuptools==82.0.1
+nutils==9.2
+numpy==1.26.4
+pyprecice==3.4.0
+
+# resonant-circuit/capacitor-python/requirements.txt
+numpy==1.26.4
+scipy==1.17.1
+pyprecice==3.4.0
+
+# resonant-circuit/coil-python/requirements.txt
+numpy==1.26.4
+scipy==1.17.1
+pyprecice==3.4.0
+
+# turek-hron-fsi3/fluid-nutils/requirements.txt
+setuptools==82.0.1
+nutils==9.2
+numpy==1.26.4
+pyprecice==3.4.0
+meshio==5.3.5
+gmsh==4.15.2
+matplotlib==3.11.0
+
+# turek-hron-fsi3/solid-nutils/requirements.txt
+setuptools==82.0.1
+nutils==9.2
+numpy==1.26.4
+pyprecice==3.4.0
+meshio==5.3.5
+gmsh==4.15.2
+matplotlib==3.11.0
+
+# two-scale-heat-conduction/macro-nutils/requirements.txt
+setuptools==82.0.1
+nutils==7.3
+numpy==1.26.4
+pyprecice==3.4.0
+
+# two-scale-heat-conduction/micro-nutils/requirements.txt
+setuptools==82.0.1
+nutils==7.3
+numpy==1.26.4
+pyprecice==3.4.0
+micro-manager-precice==0.10.1
+
+# volume-coupled-diffusion/solver-fenics/requirements.txt
+fenicsprecice==2.3.0
+numpy==1.26.4
+fenics-dijitso==2019.1.0
+fenics-dolfin~=2019.0 # unresolved (not on PyPI or no matching version)
+fenics-ffc==2019.1.0.post0
+fenics-fiat==2019.1.0
+fenics-ufl-legacy==2022.3.0
+
+# volume-coupled-flow/source-nutils/requirements.txt
+setuptools==82.0.1
+nutils==7.3
+numpy==1.26.4
+pyprecice==3.4.0
+
+# water-hammer/fluid1d-left-nutils/requirements.txt
+setuptools==82.0.1
+nutils==9.2
+numpy==1.26.4
+pyprecice==3.4.0
+matplotlib==3.11.0
+treelog==1.0
+
+# water-hammer/fluid1d-right-nutils/requirements.txt
+setuptools==82.0.1
+nutils==9.2
+numpy==1.26.4
+pyprecice==3.4.0
+matplotlib==3.11.0
+treelog==1.0
+
+# wolf-sheep-soil-creep/soil-creep-landlab/requirements.txt
+numpy==1.26.4
+matplotlib==3.11.0
+landlab==2.11.0
+pyprecice==3.4.0
+
+# wolf-sheep-soil-creep/wolf-sheep-grass-mesa/requirements.txt
+numpy==1.26.4
+matplotlib==3.11.0
+mesa==3.5.1
+pyprecice==3.4.0
+networkx==3.6.1
+
diff --git a/resonant-circuit/README.md b/resonant-circuit/README.md
index fbbcbc4e9..4f81fa45b 100644
--- a/resonant-circuit/README.md
+++ b/resonant-circuit/README.md
@@ -1,14 +1,14 @@
---
-title: Resonant Circuit
+title: Resonant circuit
permalink: tutorials-resonant-circuit.html
-keywords: MATLAB, Python
+keywords: MATLAB, Python, Julia
summary: We simulate a two-element LC circuit (one inductor and one capacitor).
---
## Setup
-The purpose of this tutorial is to illustrate the usage of preCICE to couple MATLAB code. Two different MATLAB solvers will be coupled to simulate a two-element LC circuit. This type of circuit consists of a very simple system with one inductor and one capacitor:
+Two different solvers are coupled to simulate a two-element LC circuit. This type of circuit consists of a simple system with one inductor and one capacitor:
![LC circuit diagram [1]](images/tutorials-resonant-circuit-diagram.svg)
@@ -20,7 +20,7 @@ $I(t) = -C \frac{\text{d}U}{\text{d}t}$
where $I$ is the current and $U$ the voltage of the circuit.
-Each of these equations is going to be solved by a different MATLAB solver. Note that, as only one scalar is solved per equation, this is a 0+1 dimensional problem.
+Each of these equations is solved by a different solver. Note that, as only one scalar is solved per equation, this is a 0+1 dimensional problem.
## Configuration
@@ -31,43 +31,42 @@ preCICE configuration (image generated using the [precice-config-visualizer](htt
## Available solvers
* *MATLAB* A solver using the [MATLAB bindings](https://precice.org/installation-bindings-matlab.html).
- Before running this tutorial, follow the [instructions](https://precice.org/installation-bindings-matlab.html) to correctly install the MATLAB bindings.
* *Python* A solver using the preCICE [Python bindings](https://precice.org/installation-bindings-python.html).
+* *Julia* A solver using the preCICE [Julia bindings](https://precice.org/installation-bindings-julia.html).
## Running the simulation
-### MATLAB
+All listed solvers can be used to run the simulation. Open two separate terminals and start the desired capacitor and coil participants by calling the respective run script. For example:
-For running this example, first get into one of the solver folders and open a MATLAB instance.
-Afterward, do the same for the second solver.
-After adding the MATLAB bindings to the MATLAB path (in both instances), run the following commands:
-
-In the first MATLAB instance, one can run the solver for the current:
-
-```MATLAB
-coil
+```bash
+cd capacitor-python
+./run.sh
```
-And in the second MATLAB instance, the solver for the voltage:
+and
-```MATLAB
-capacitor
+```bash
+cd coil-julia
+./run.sh
```
-The preCICE configuration file is hard-coded as `precice-config.xml` in the solvers.
+### Running the MATLAB participants
+
+For running this example in the MATLAB GUI, first get into each of the solver folders and open a MATLAB instance for each.
+After adding the MATLAB bindings to the MATLAB path (in both instances), run the `coil` and `capacitor` commands in the two windows.
-#### Running from terminal
+The path to the preCICE configuration file is hard-coded as `precice-config.xml` in the solvers.
-If you prefer to not open the MATLAB GUIs, you can alternatively use two shells instead.
+If you prefer not to use the MATLAB GUI, you can alternatively use two shells instead.
For that, modify the path in the file `matlab-bindings-path.sh` found in the base directory of this tutorial to the path to your MATLAB bindings.
By doing that, you can now open two shells and switch into the directories `capacitor-matlab` and `coil-matlab` and execute the `run.sh` scripts.
## Post-processing
-As we defined a watchpoint on the 'Capacitor' participant (see `precice-config.xml`), we can plot it with gnuplot using the script `plot-solution.sh.` You need to specify the directory of the selected solid participant as a command line argument, so that the script can pick-up the desired watchpoint file, e.g. `./plot-solution.sh capacitor-python`. The resulting graph shows the voltage and current exchanged between the two participants.
+As we defined a watchpoint on the 'Capacitor' participant (see `precice-config.xml`), we can plot it with gnuplot using the script `plot-solution.sh`. You need to specify the directory of the selected solid participant as a command line argument, so that the script can pick-up the desired watchpoint file, e.g., `./plot-solution.sh capacitor-python`. The resulting graph shows the voltage and current exchanged between the two participants.
-Additionally, the MATLAB participant `capacitor-matlab` records the current and voltage over time. At the end of the simulation it creates a plot with the computed waveforms of current and voltage, as well as the analytical solution.
+Additionally, the `capacitor-matlab` case records the current and voltage over time. At the end of the simulation, it creates a plot with the computed waveforms of current and voltage, as well as the analytical solution.
After successfully running the coupling, one can find the curves in the folder `capacitor-matlab` as `Curves.png`.
diff --git a/resonant-circuit/capacitor-julia/capacitor.jl b/resonant-circuit/capacitor-julia/capacitor.jl
new file mode 100644
index 000000000..9219c5cae
--- /dev/null
+++ b/resonant-circuit/capacitor-julia/capacitor.jl
@@ -0,0 +1,82 @@
+using PreCICE
+using DifferentialEquations
+
+# Initialize and configure preCICE
+participant = PreCICE.createParticipant("Capacitor", "../precice-config.xml", 0, 1)
+
+# Geometry IDs. As it is a 0-D simulation, only one vertex is necessary.
+mesh_name = "Capacitor-Mesh"
+
+dimensions = PreCICE.getMeshDimensions(mesh_name)
+
+vertex_ids = PreCICE.setMeshVertices(mesh_name, zeros((1,dimensions)))
+
+let
+ # Data IDs
+ read_data_name = "Current"
+ write_data_name = "Voltage"
+
+ # Simulation parameters and initial condition
+ C = 2 # Capacitance of the capacitor
+ L = 1 # Inductance of the coil
+ t0 = 0 # Initial simulation time
+ t_max = 10 # End simulation time
+ Io = 1 # Initial current
+ phi = 0 # Phase of the signal
+
+ w0 = 1 / sqrt(L * C) # Resonant frequency
+ U0 = -w0 * L * Io * sin(phi) # Initial condition for U
+
+ function f_U(u, p, t)
+ (dt, C, mesh_name, read_data_name, vertex_ids) = p
+ I = PreCICE.readData(mesh_name, read_data_name, vertex_ids, dt)
+ return -I[1] / C # Time derivative of U
+ end
+
+ # Initialize simulation
+ if PreCICE.requiresInitialData()
+ PreCICE.writeData(mesh_name, write_data_name, vertex_ids, I0)
+ end
+ PreCICE.initialize()
+
+ solver_dt = PreCICE.getMaxTimeStepSize()
+
+ # Start simulation
+ t = t0
+ U0_checkpoint = U0
+ t_checkpoint = t
+ while PreCICE.isCouplingOngoing()
+
+ # Record checkpoint if necessary
+ if PreCICE.requiresWritingCheckpoint()
+ U0_checkpoint = U0
+ t_checkpoint = t
+ end
+
+ # Make Simulation Step
+ precice_dt = PreCICE.getMaxTimeStepSize()
+ dt = min(precice_dt, solver_dt)
+ t_span = (t, t + dt)
+ params = (dt, C, mesh_name, read_data_name, vertex_ids)
+ prob = ODEProblem(f_U, U0, t_span, params)
+ # https://docs.sciml.ai/DiffEqDocs/stable/basics/common_solver_opts
+ sol = solve(prob, Tsit5(), reltol=1e-12, abstol=1e-12)
+
+ # Exchange data
+ evals = max(length(sol.t), 3) # at least do 3 substeps to allow cubic interpolation
+ for i in range(1,evals)
+ U0 = sol(t_span[1] + i * dt / evals)
+ PreCICE.writeData(mesh_name, write_data_name, vertex_ids, fill(U0, (1,1)))
+ PreCICE.advance(dt / evals)
+ end
+ t = t + dt
+
+ # Recover checkpoint if not converged
+ if PreCICE.requiresReadingCheckpoint()
+ U0 = U0_checkpoint
+ t = t_checkpoint
+ end
+ end
+ # Stop coupling
+ PreCICE.finalize()
+end
\ No newline at end of file
diff --git a/resonant-circuit/capacitor-julia/clean.sh b/resonant-circuit/capacitor-julia/clean.sh
new file mode 100755
index 000000000..f9c06b0f3
--- /dev/null
+++ b/resonant-circuit/capacitor-julia/clean.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+set -e -u
+
+. ../../tools/cleaning-tools.sh
+
+clean_precice_logs .
+clean_case_logs .
\ No newline at end of file
diff --git a/resonant-circuit/capacitor-julia/run.sh b/resonant-circuit/capacitor-julia/run.sh
new file mode 100755
index 000000000..a61d1fa67
--- /dev/null
+++ b/resonant-circuit/capacitor-julia/run.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+set -e -u
+
+. ../../tools/log.sh
+exec > >(tee --append "$LOGFILE") 2>&1
+
+julia --project=Project.toml -e 'using Pkg; Pkg.add("DifferentialEquations"); Pkg.add("PreCICE"); Pkg.instantiate();'
+julia --project=Project.toml capacitor.jl
+
+close_log
\ No newline at end of file
diff --git a/resonant-circuit/capacitor-matlab/clean.sh b/resonant-circuit/capacitor-matlab/clean.sh
index 6a77c6d6c..e0b5926f1 100755
--- a/resonant-circuit/capacitor-matlab/clean.sh
+++ b/resonant-circuit/capacitor-matlab/clean.sh
@@ -1,8 +1,7 @@
-#!/bin/sh
+#!/usr/bin/env bash
set -e -u
-rm ./*.png ./*.mat
-
. ../../tools/cleaning-tools.sh
clean_matlab .
+rm -f ./*.png ./*.mat
diff --git a/resonant-circuit/capacitor-matlab/run.sh b/resonant-circuit/capacitor-matlab/run.sh
index 37a830a91..906b25220 100755
--- a/resonant-circuit/capacitor-matlab/run.sh
+++ b/resonant-circuit/capacitor-matlab/run.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env bash
# Run MATLAB code without GUI
matlab -nodisplay -r "capacitor;exit;"
diff --git a/resonant-circuit/capacitor-python/clean.sh b/resonant-circuit/capacitor-python/clean.sh
new file mode 100755
index 000000000..f9c06b0f3
--- /dev/null
+++ b/resonant-circuit/capacitor-python/clean.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+set -e -u
+
+. ../../tools/cleaning-tools.sh
+
+clean_precice_logs .
+clean_case_logs .
\ No newline at end of file
diff --git a/resonant-circuit/capacitor-python/requirements.txt b/resonant-circuit/capacitor-python/requirements.txt
index 2b8edf2ba..814a5c7dc 100644
--- a/resonant-circuit/capacitor-python/requirements.txt
+++ b/resonant-circuit/capacitor-python/requirements.txt
@@ -1,3 +1,3 @@
numpy >1, <2
-scipy
+scipy>=1.10,<2
pyprecice~=3.0
diff --git a/resonant-circuit/capacitor-python/run.sh b/resonant-circuit/capacitor-python/run.sh
index 042124adc..4b9fa3ba5 100755
--- a/resonant-circuit/capacitor-python/run.sh
+++ b/resonant-circuit/capacitor-python/run.sh
@@ -4,11 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
python3 capacitor.py
diff --git a/resonant-circuit/coil-julia/clean.sh b/resonant-circuit/coil-julia/clean.sh
new file mode 100755
index 000000000..f9c06b0f3
--- /dev/null
+++ b/resonant-circuit/coil-julia/clean.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+set -e -u
+
+. ../../tools/cleaning-tools.sh
+
+clean_precice_logs .
+clean_case_logs .
\ No newline at end of file
diff --git a/resonant-circuit/coil-julia/coil.jl b/resonant-circuit/coil-julia/coil.jl
new file mode 100644
index 000000000..6cd949ebb
--- /dev/null
+++ b/resonant-circuit/coil-julia/coil.jl
@@ -0,0 +1,85 @@
+using PreCICE
+using DifferentialEquations
+
+# Initialize and configure preCICE
+participant = PreCICE.createParticipant("Coil", "../precice-config.xml", 0, 1)
+
+# Geometry IDs. As it is a 0-D simulation, only one vertex is necessary.
+mesh_name = "Coil-Mesh"
+
+dimensions = PreCICE.getMeshDimensions(mesh_name)
+
+vertex_ids = PreCICE.setMeshVertices(mesh_name, zeros((1,dimensions)))
+
+let
+ # Data IDs
+ read_data_name = "Voltage"
+ write_data_name = "Current"
+
+ # Simulation parameters and initial condition
+ C = 2 # Capacitance of the capacitor
+ L = 1 # Inductance of the coil
+ t0 = 0 # Initial simulation time
+ Io = 1 # Initial current
+ phi = 0 # Phase of the signal
+
+ w0 = 1 / sqrt(L * C) # Resonant frequency
+ I0 = Io * cos(phi) # Initial condition for I
+
+ # to estimate cost
+ f_evals = 0
+
+ function f_I(u, p, t)
+ f_evals += 1
+ (dt, L, mesh_name, read_data_name, vertex_ids) = p
+ U = PreCICE.readData(mesh_name, read_data_name, vertex_ids, dt)
+ return U[1] / L # Time derivative of I; ODE determining capacitor
+ end
+
+ # Initialize simulation
+ if PreCICE.requiresInitialData()
+ PreCICE.writeData(mesh_name, write_data_name, vertex_ids, I0)
+ end
+ PreCICE.initialize()
+
+ solver_dt = PreCICE.getMaxTimeStepSize()
+
+ # Start simulation
+ t = t0
+ I0_checkpoint = I0
+ t_checkpoint = t
+ while PreCICE.isCouplingOngoing()
+
+ # Record checkpoint if necessary
+ if PreCICE.requiresWritingCheckpoint()
+ I0_checkpoint = I0
+ t_checkpoint = t
+ end
+
+ # Make Simulation Step
+ precice_dt = PreCICE.getMaxTimeStepSize()
+ dt = min(precice_dt, solver_dt)
+ t_span = (t, t + dt)
+ params = (dt, L, mesh_name, read_data_name, vertex_ids)
+ prob = ODEProblem(f_I, I0, t_span, params)
+ # https://docs.sciml.ai/DiffEqDocs/stable/basics/common_solver_opts
+ sol = solve(prob, Tsit5(), reltol=1e-12, abstol=1e-12)
+
+ # Exchange data
+ evals = max(length(sol.t), 3) # at least do 3 substeps to allow cubic interpolation
+ for i in range(1,evals)
+ I0 = sol(t_span[1] + i * dt / evals)
+ PreCICE.writeData(mesh_name, write_data_name, vertex_ids, fill(I0, (1,1)))
+ PreCICE.advance(dt / evals)
+ end
+ t = t + dt
+
+ # Recover checkpoint if not converged
+ if PreCICE.requiresReadingCheckpoint()
+ I0 = I0_checkpoint
+ t = t_checkpoint
+ end
+ end
+ # Stop coupling
+ PreCICE.finalize()
+end
\ No newline at end of file
diff --git a/resonant-circuit/coil-julia/run.sh b/resonant-circuit/coil-julia/run.sh
new file mode 100755
index 000000000..6340410ae
--- /dev/null
+++ b/resonant-circuit/coil-julia/run.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+set -e -u
+
+. ../../tools/log.sh
+exec > >(tee --append "$LOGFILE") 2>&1
+
+julia --project=Project.toml -e 'using Pkg; Pkg.add("DifferentialEquations"); Pkg.add("PreCICE"); Pkg.instantiate();'
+julia --project=Project.toml coil.jl
+
+close_log
\ No newline at end of file
diff --git a/resonant-circuit/coil-matlab/clean.sh b/resonant-circuit/coil-matlab/clean.sh
index 5c6294dfa..8dc0ec32b 100755
--- a/resonant-circuit/coil-matlab/clean.sh
+++ b/resonant-circuit/coil-matlab/clean.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env bash
set -e -u
. ../../tools/cleaning-tools.sh
diff --git a/resonant-circuit/coil-matlab/run.sh b/resonant-circuit/coil-matlab/run.sh
index 2c5e471a7..085ae73f2 100755
--- a/resonant-circuit/coil-matlab/run.sh
+++ b/resonant-circuit/coil-matlab/run.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env bash
# Run MATLAB code without GUI
matlab -nodisplay -r "coil;exit;"
diff --git a/resonant-circuit/coil-python/clean.sh b/resonant-circuit/coil-python/clean.sh
new file mode 100755
index 000000000..f9c06b0f3
--- /dev/null
+++ b/resonant-circuit/coil-python/clean.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+set -e -u
+
+. ../../tools/cleaning-tools.sh
+
+clean_precice_logs .
+clean_case_logs .
\ No newline at end of file
diff --git a/resonant-circuit/coil-python/requirements.txt b/resonant-circuit/coil-python/requirements.txt
index 2b8edf2ba..814a5c7dc 100644
--- a/resonant-circuit/coil-python/requirements.txt
+++ b/resonant-circuit/coil-python/requirements.txt
@@ -1,3 +1,3 @@
numpy >1, <2
-scipy
+scipy>=1.10,<2
pyprecice~=3.0
diff --git a/resonant-circuit/coil-python/run.sh b/resonant-circuit/coil-python/run.sh
index 248944c23..6c2a260f4 100755
--- a/resonant-circuit/coil-python/run.sh
+++ b/resonant-circuit/coil-python/run.sh
@@ -4,11 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
python3 coil.py
diff --git a/resonant-circuit/metadata.yaml b/resonant-circuit/metadata.yaml
new file mode 100644
index 000000000..c46c1adbf
--- /dev/null
+++ b/resonant-circuit/metadata.yaml
@@ -0,0 +1,45 @@
+name: Resonant circuit
+path: resonant-circuit
+url: https://precice.org/tutorials-resonant-circuit.html
+
+participants:
+ - Capacitor
+ - Coil
+
+cases:
+ # capacitor-julia:
+ # participant: Capacitor
+ # directory: ./capacitor-julia
+ # run: ./run.sh
+ # component: julia-bindings
+
+ # capacitor-matlab:
+ # participant: Capacitor
+ # directory: ./capacitor-matlab
+ # run: ./run.sh
+ # component: matlab-bindings
+
+ capacitor-python:
+ participant: Capacitor
+ directory: ./capacitor-python
+ run: ./run.sh
+ component: python-bindings
+
+ # coil-julia:
+ # participant: Coil
+ # directory: ./coil-julia
+ # run: ./run.sh
+ # component: julia-bindings
+
+ # coil-matlab:
+ # participant: Coil
+ # directory: ./coil-matlab
+ # run: ./run.sh
+ # component: matlab-bindings
+
+ coil-python:
+ participant: Coil
+ directory: ./coil-python
+ run: ./run.sh
+ component: python-bindings
+
\ No newline at end of file
diff --git a/resonant-circuit/plot-solution.sh b/resonant-circuit/plot-solution.sh
index 85f5b901c..bd2158b27 100755
--- a/resonant-circuit/plot-solution.sh
+++ b/resonant-circuit/plot-solution.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env bash
if [ "${1:-}" = "" ]; then
echo "No target directory specified. Please specify the directory of the participant containing the watchpoint, e.g. ./plot-displacement.sh coil-python."
diff --git a/resonant-circuit/precice-config.xml b/resonant-circuit/precice-config.xml
index cda70ee19..fb72e5772 100644
--- a/resonant-circuit/precice-config.xml
+++ b/resonant-circuit/precice-config.xml
@@ -1,5 +1,12 @@
+
+
+
+
diff --git a/resonant-circuit/reference-results/capacitor-python_coil-python.tar.gz b/resonant-circuit/reference-results/capacitor-python_coil-python.tar.gz
new file mode 100644
index 000000000..5623609a9
--- /dev/null
+++ b/resonant-circuit/reference-results/capacitor-python_coil-python.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:5f86feb2df61aff94c0bada250a8574f65b671d88af0431683e19e2f1730991e
+size 2625
diff --git a/resonant-circuit/reference-results/reference_results.metadata b/resonant-circuit/reference-results/reference_results.metadata
new file mode 100644
index 000000000..7204326cb
--- /dev/null
+++ b/resonant-circuit/reference-results/reference_results.metadata
@@ -0,0 +1,71 @@
+
+
+# Reference Results
+
+This file contains an overview of the results over the reference results as well as the arguments used to generate them.
+We also include some information on the machine used to generate them
+
+## List of files
+
+| name | time | sha256 |
+|------|------|-------|
+| capacitor-python_coil-python.tar.gz | 2026-05-30 14:00:24 | 5f86feb2df61aff94c0bada250a8574f65b671d88af0431683e19e2f1730991e |
+
+## List of arguments used to generate the files
+
+| name | value |
+|------|------|
+| PLATFORM | ubuntu_2404 |
+| CALCULIX_VERSION | 2.20 |
+| DUNE_VERSION | 2.9 |
+| DUMUX_VERSION | 3.7 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | 89c82d5 |
+| PRECICE_PRESET | production-audit |
+| PRECICE_UID | 1003 |
+| PRECICE_GID | 1003 |
+## Information about the machine
+
+### uname -a
+
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+
+
+### lscpu
+
+Architecture: x86_64
+CPU op-mode(s): 32-bit, 64-bit
+Address sizes: 45 bits physical, 48 bits virtual
+Byte Order: Little Endian
+CPU(s): 4
+On-line CPU(s) list: 0-3
+Vendor ID: GenuineIntel
+Model name: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz
+CPU family: 6
+Model: 85
+Thread(s) per core: 1
+Core(s) per socket: 1
+Socket(s): 4
+Stepping: 4
+BogoMIPS: 4199.99
+Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat pku ospke md_clear flush_l1d arch_capabilities
+Hypervisor vendor: VMware
+Virtualization type: full
+L1d cache: 128 KiB (4 instances)
+L1i cache: 128 KiB (4 instances)
+L2 cache: 4 MiB (4 instances)
+L3 cache: 88 MiB (4 instances)
+NUMA node(s): 1
+NUMA node0 CPU(s): 0-3
diff --git a/tools/cleaning-tools.sh b/tools/cleaning-tools.sh
index a1d029f4a..450ba407b 100755
--- a/tools/cleaning-tools.sh
+++ b/tools/cleaning-tools.sh
@@ -18,7 +18,7 @@ clean_tutorial() {
fi
for case in */; do
- if [ "${case}" = images/ ] || [ "${case}" = reference-results/ ]; then
+ if [ "${case}" = images/ ] || [ "${case}" = reference-results/ ] || [ "${case}" = dumux/ ]; then
continue
fi
case "${case}" in solver*)
@@ -149,7 +149,7 @@ clean_openfoam() {
if [ -n "${WM_PROJECT:-}" ] || error "No OpenFOAM environment is active."; then
# shellcheck disable=SC1090 # This is an OpenFOAM file which we don't need to check
. "${WM_PROJECT_DIR}/bin/tools/CleanFunctions"
- cleanCase > /dev/null
+ region="*" cleanCase > /dev/null
rm -rfv 0/uniform/functionObjects/functionObjectProperties history
fi
clean_precice_logs .
diff --git a/tools/report_tutorial_requirements.py b/tools/report_tutorial_requirements.py
new file mode 100644
index 000000000..e85e6a2fe
--- /dev/null
+++ b/tools/report_tutorial_requirements.py
@@ -0,0 +1,200 @@
+#!/usr/bin/env python3
+"""
+Report resolved Python dependency versions for tutorial requirements.txt files.
+
+Scans every tutorial requirements.txt (excluding tools/tests/), queries PyPI for
+the latest version satisfying each constraint, and writes requirements-reference.txt.
+
+Run from the repository root:
+ python3 tools/report_tutorial_requirements.py
+ python3 tools/report_tutorial_requirements.py --check
+"""
+from __future__ import annotations
+
+import argparse
+import json
+import re
+import subprocess
+import sys
+import urllib.error
+import urllib.request
+from datetime import datetime, timezone
+from pathlib import Path
+
+from packaging.requirements import Requirement
+from packaging.specifiers import SpecifierSet
+from packaging.utils import canonicalize_name
+from packaging.version import Version
+
+REPO_ROOT = Path(__file__).resolve().parent.parent
+REFERENCE_FILE = REPO_ROOT / "requirements-reference.txt"
+EXCLUDED_RELATIVE = {
+ "tools/tests/requirements.txt",
+ # Not a pip requirements file (lists stdlib os, unpinned vtk); see develop naming quirk.
+ "flow-over-heated-plate/plot-final-interface-temperature-requirements.txt",
+}
+
+_PYPI_VERSIONS_CACHE: dict[str, list[Version]] = {}
+_RESOLVED_CACHE: dict[str, str | None] = {}
+
+_HEADER = """\
+# Pinned Python dependency versions for preCICE tutorial distributions.
+# Reference manifest only: tutorial run scripts keep using loose requirements.txt constraints.
+# Generated by tools/report_tutorial_requirements.py — do not edit manually.
+# Generated: {timestamp}
+
+"""
+
+
+def discover_requirements_files() -> list[Path]:
+ """Return git-tracked tutorial requirements.txt files only."""
+ result = subprocess.run(
+ ["git", "ls-files", "--", "**/requirements.txt"],
+ cwd=REPO_ROOT,
+ capture_output=True,
+ text=True,
+ check=True,
+ )
+ files: list[Path] = []
+ for line in result.stdout.splitlines():
+ relative = line.strip()
+ if not relative or relative in EXCLUDED_RELATIVE:
+ continue
+ files.append(REPO_ROOT / relative)
+ return sorted(files)
+
+
+def parse_requirement_line(line: str) -> str | None:
+ stripped = line.strip()
+ if not stripped or stripped.startswith("#"):
+ return None
+ if " #" in stripped:
+ stripped = stripped.split(" #", 1)[0].strip()
+ return stripped or None
+
+
+def fetch_pypi_versions(package_name: str) -> list[Version]:
+ canonical = canonicalize_name(package_name)
+ if canonical in _PYPI_VERSIONS_CACHE:
+ return _PYPI_VERSIONS_CACHE[canonical]
+
+ url = f"https://pypi.org/pypi/{package_name}/json"
+ request = urllib.request.Request(url, headers={"Accept": "application/json"})
+ try:
+ with urllib.request.urlopen(request, timeout=30) as response:
+ payload = json.load(response)
+ except urllib.error.HTTPError as exc:
+ if exc.code == 404:
+ return []
+ raise
+
+ versions: list[Version] = []
+ for version_str in payload.get("releases", {}):
+ try:
+ versions.append(Version(version_str))
+ except Exception:
+ continue
+ _PYPI_VERSIONS_CACHE[canonical] = versions
+ return versions
+
+
+def resolve_pypi_version(requirement: Requirement) -> str | None:
+ cache_key = str(requirement)
+ if cache_key in _RESOLVED_CACHE:
+ return _RESOLVED_CACHE[cache_key]
+
+ if requirement.url:
+ _RESOLVED_CACHE[cache_key] = None
+ return None
+
+ versions = fetch_pypi_versions(requirement.name)
+ if not versions:
+ _RESOLVED_CACHE[cache_key] = None
+ return None
+
+ specifier = requirement.specifier if str(requirement.specifier) else SpecifierSet()
+ compatible = [version for version in versions if specifier.contains(version, prereleases=False)]
+ if not compatible:
+ _RESOLVED_CACHE[cache_key] = None
+ return None
+ resolved = str(max(compatible))
+ _RESOLVED_CACHE[cache_key] = resolved
+ return resolved
+
+
+def format_resolved_requirement(requirement_line: str) -> str:
+ requirement = Requirement(requirement_line)
+ if requirement.url:
+ return requirement_line
+
+ resolved = resolve_pypi_version(requirement)
+ if resolved is None:
+ return f"{requirement_line} # unresolved (not on PyPI or no matching version)"
+ return f"{requirement.name}=={resolved}"
+
+
+def generate_reference_text() -> str:
+ timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
+ sections: list[str] = [_HEADER.format(timestamp=timestamp)]
+
+ for req_file in discover_requirements_files():
+ relative = req_file.relative_to(REPO_ROOT).as_posix()
+ sections.append(f"# {relative}\n")
+ for line in req_file.read_text().splitlines():
+ requirement_line = parse_requirement_line(line)
+ if requirement_line is None:
+ continue
+ sections.append(format_resolved_requirement(requirement_line) + "\n")
+ sections.append("\n")
+
+ return "".join(sections)
+
+
+def normalize_for_check(text: str) -> str:
+ """Ignore generation timestamp when comparing reference files."""
+ return re.sub(r"^# Generated: .*\n", "# Generated: \n", text, count=1, flags=re.MULTILINE)
+
+
+def main() -> int:
+ parser = argparse.ArgumentParser(
+ description="Report resolved tutorial Python dependencies from PyPI"
+ )
+ parser.add_argument(
+ "--check",
+ action="store_true",
+ help="Exit 1 if requirements-reference.txt is out of date",
+ )
+ parser.add_argument(
+ "--output",
+ type=Path,
+ default=REFERENCE_FILE,
+ help="Output path (default: requirements-reference.txt at repo root)",
+ )
+ args = parser.parse_args()
+
+ generated = generate_reference_text()
+
+ if args.check:
+ if not args.output.exists():
+ print(
+ f"ERROR: {args.output} not found. Run: python3 tools/report_tutorial_requirements.py",
+ file=sys.stderr,
+ )
+ return 1
+ current = args.output.read_text()
+ if normalize_for_check(current) != normalize_for_check(generated):
+ print(
+ f"ERROR: {args.output} is out of date. Run: python3 tools/report_tutorial_requirements.py",
+ file=sys.stderr,
+ )
+ return 1
+ print(f"OK: {args.output} is up to date")
+ return 0
+
+ args.output.write_text(generated)
+ print(f"Wrote {args.output}")
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/tools/run-foam-extend.sh b/tools/run-foam-extend.sh
new file mode 100755
index 000000000..19484d705
--- /dev/null
+++ b/tools/run-foam-extend.sh
@@ -0,0 +1,67 @@
+#!/usr/bin/env sh
+set -e # Not setting -u as it gets triggered by the OpenFOAM RunFunctions
+
+# Prepare an (intentionally empty) .foam file for the ParaView OpenFOAM reader
+CASENAME="$(pwd | xargs basename)"
+touch "$CASENAME.foam"
+
+# Keep a backup of the files to modify
+echo "backing up the original files (copies: 0/U.orig, system/controlDict.orig, constant/dynamicMeshDict.orig)"
+cp 0/U 0/U.orig
+cp system/controlDict system/controlDict.orig
+cp constant/dynamicMeshDict constant/dynamicMeshDict.orig
+
+# Modify code for foam-extend
+echo "modifying everything now"
+sed -i "s/noSlip;/noSlipWall;/g" 0/U
+sed -i "s,application pimpleFoam;,//application pimpleFoam;,g" system/controlDict
+sed -i "s,// application pimpleDyMFoam;,application pimpleDyMFoam;,g" system/controlDict
+sed -i '41i\ \ \ \ "liblduSolvers.so"' system/controlDict
+sed -i '41i\ \ \ \ "libforces.so"' system/controlDict
+sed -i "s,writeCompression off,writeCompression uncompressed,g" system/controlDict
+sed -i "s,\/\* uncomment,// FOAMEXTENDBEGIN,g" system/controlDict
+sed -i "s,\*\/ // foam-extend,// FOAMEXTENDEND,g" system/controlDict
+
+sed -i "s,\/\* uncomment,// FOAMEXTENDBEGIN,g" system/fvSchemes
+sed -i "s,\*\/ // foam-extend,// FOAMEXTENDEND,g" system/fvSchemes
+
+sed -i "s,\/\* uncomment,// FOAMEXTENDBEGIN,g" system/fvSolution
+sed -i "s,\*\/ // foam-extend,// FOAMEXTENDEND,g" system/fvSolution
+
+sed -i "s/libfvMotionSolvers\./libfvMotionSolver\./g" constant/dynamicMeshDict
+sed -i "s,\/\* uncomment,// FOAMEXTENDBEGIN,g" constant/dynamicMeshDict
+sed -i "s,\*\/ // foam-extend,// FOAMEXTENDEND,g" constant/dynamicMeshDict
+
+# OpenFOAM run functions: getApplication, getNumberOfProcessors
+# shellcheck disable=SC1090 # This is an OpenFOAM file which we don't need to check
+. "${WM_PROJECT_DIR}/bin/tools/RunFunctions"
+solver=$(getApplication | cut -f 1 -d " " | sed '\~//~d')
+if [ "${1:-}" = "-parallel" ]; then
+ procs=$(getNumberOfProcessors)
+ decomposePar -force
+ mpirun -np "${procs}" "${solver}" -parallel
+ reconstructPar
+else
+ ${solver}
+fi
+
+# Reverse code for OpenFOAM
+#rm -rf constant/polyMesh
+#sed -i "s/noSlipWall;/noSlip;/g" 0/U
+#sed -i "s,application pimpleDyMFoam;,// application pimpleDyMFoam;,g" system/controlDict
+#sed -i "s,//application pimpleFoam;,application pimpleFoam;,g" system/controlDict
+#sed -i '/ "liblduSolvers.so"/d' system/controlDict
+#sed -i '/ "libforces.so/d' system/controlDict
+#sed -i "s,writeCompression uncompressed,writeCompression off,g" system/controlDict
+#sed -i "s,// FOAMEXTENDBEGIN,\/\* uncomment,g" system/controlDict
+#sed -i "s,// FOAMEXTENDEND,\*\/ // foam-extend,g" system/controlDict
+#
+#sed -i "s,// FOAMEXTENDBEGIN,\/\* uncomment,g" system/fvSchemes
+#sed -i "s,// FOAMEXTENDEND,\*\/ // foam-extend,g" system/fvSchemes
+#
+#sed -i "s,// FOAMEXTENDBEGIN,\/\* uncomment,g" system/fvSolution
+#sed -i "s,// FOAMEXTENDEND,\*\/ // foam-extend,g" system/fvSolution
+#
+#sed -i "s/libfvMotionSolver\./libfvMotionSolvers\./g" constant/dynamicMeshDict
+#sed -i "s,// FOAMEXTENDBEGIN,\/\* uncomment,g" constant/dynamicMeshDict
+#sed -i "s,// FOAMEXTENDEND,\*\/ // foam-extend,g" constant/dynamicMeshDict
diff --git a/tools/tests/.gitignore b/tools/tests/.gitignore
deleted file mode 100644
index 3072e6ffe..000000000
--- a/tools/tests/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*.pyc
-*.pyo
\ No newline at end of file
diff --git a/tools/tests/README.md b/tools/tests/README.md
index bd935965b..5183dc469 100644
--- a/tools/tests/README.md
+++ b/tools/tests/README.md
@@ -6,134 +6,155 @@ keywords: pages, development, tests
summary: "Test complete simulations combining preCICE components of specific versions."
---
-The tutorials repository hosts cases that need multiple components from the preCICE ecosystem to run. This directory provides tools that can automatically run complete simulations, using different versions of each component, and compare the results to references. While the main purpose is to run complete tests in the continuous integration workflows of preCICE, you can also run these tests on your laptop.
+The tutorials repository hosts cases that need multiple components from the preCICE ecosystem to run. Te system tests automatically run tutorials combining the required components and compare the numerical results to references. While the main purpose is to run complete tests in the continuous integration workflows of preCICE, you can also run these tests on your laptop.
-Read more about the system tests in the publication [System Regression Tests for the preCICE Coupling Ecosystem](https://doi.org/10.14279/eceasst.v83.2614).
-
-[](https://doi.org/10.14279/eceasst.v83.2614)
+## Running
-## Running the system tests
+The main workflow for the user is executing the `systemtests.py` script, which is the same that the [GitHub Actions workflow](https://github.com/precice/tutorials/actions/workflows/system-tests-latest-components.yml) executes. Depending on the options given to the script, it reads in the respective metadata files and generates `docker-compose.yaml` files that can start a fully-defined coupled simulation. For arguments that are not provided, default values from `components.yaml` are used.
-The main workflow for the user is executing the `systemtests.py` script. Depending on the options given to the script, it reads in the respective metadata files and generates `docker-compose.yaml` files that can start a fully-defined coupled simulation.
+### Manual and nightly runs on GitHub
-### Running the tests for a preCICE release
+The [System tests (manual/nightly)](https://github.com/precice/tutorials/actions/workflows/system-tests-latest-components.yml) workflow executes the `release` test suite nightly and can also be triggered manually.
-Workflow for the preCICE v3 release testing:
+On the workflow page, click `Run workflow`. The default values will execute the `release` test suite using the latest `develop` branches of every component. If you want to override the version of some component, specify it in the respective field. Commit hashes, branches, and tags are all accepted. Branches and tags will get automatically resolved to their current commit on GitHub before starting any test, and all tests will use the same version of any common component.
-1. Collect the Git commits/tags of all components you want to test. The caching mechanism cannot detect changes based on branch names. The same effect might be encountered when rebasing and force-pushing the release branch.
-2. In your terminal, navigate to the tutorials repository
-3. Trigger the GitHub Actions Workflow. Until we merge the workflow to develop, this can only happen via the [GitHub CLI](https://cli.github.com/):
+The available test suites are found in [`tests.yaml`](https://github.com/precice/tutorials/blob/develop/tools/tests/tests.yaml) and common values are:
- ```bash
- gh workflow run run_testsuite_manual.yml -f suites=release_test -f build_args="PRECICE_REF:v3.1.1,PRECICE_PRESET:production-audit,OPENFOAM_ADAPTER_REF:v1.3.0,PYTHON_BINDINGS_REF:v3.1.0,FENICS_ADAPTER_REF:v2.1.0,SU2_VERSION:7.5.1,SU2_ADAPTER_REF:64d4aff,DEALII_ADAPTER_REF:02c5d18,TUTORIALS_REF:340b447" --ref=develop
- ```
+- `quickstart`, `elastic-tube-1d`, or any other tutorial (see [exceptions](https://github.com/precice/tutorials/issues/448))
+- `openfoam-adapter`, `micro-manager`, `fmi-runner`, or similar test cases involving the respective component
+- `precice` is a subset of cases that cover a range of preCICE features
+- `release` is for all available but some very long or known to fail tests
+- `extra` is for some longer tests
+- `expected-to-fail`, `selected`, and `system-tests-dev` for some special cases
-4. Go to the tutorials [Actions](https://github.com/precice/tutorials/actions) page and find the running workflow
-5. Check the status and the runtimes of each tutorial:
+The `Use workflow from` is a default option of GitHub Actions that concerns the GHA workflow file itself.
- - Very small build times mean that the test is using cached container layers
- - Most commonly, you will see tests failing with `Fieldcompare returned non zero exit code`. You will need to check the logs, but if the fieldcompare time is significant, this typically means that the numerical results differ above the tolerance (the test works!).
+### Running from a pull request
-6. Download the build artifacts from Summary > runs.
+Several repositories include a workflow that allows triggering the system tests by adding the `trigger-system-tests` label to the pull request. The event is triggered only at the moment of adding the label, so you need to remove the label and add it again if needed.
- - In there, you may want to check the `system-tests-stdout.log` and `system-tests-stderr.log` files.
- - The produced results are in `precice-exports/`, the reference results in `reference-results-unpacked`.
- - Compare using, e.g., ParaView or [fieldcompare](https://gitlab.com/dglaeser/fieldcompare): `fieldcompare dir precice-exports/ reference/`. The `--diff` option will give you `precice-exports/diff_*.vtu` files, while you can also try different tolerances with `-rtol` and `-atol`.
+See the [system tests workflow in the OpenFOAM adapter](https://github.com/precice/openfoam-adapter/blob/develop/.github/workflows/system-tests.yaml) for an example.
-### Running specific test suites
+### Running from the GitHub CLI
-To test a certain test-suite defined in `tests.yaml`, use:
+The [GitHub CLI](https://cli.github.com/) allows triggering workflows of a GitHub project. For example:
```bash
-python3 systemtests.py --suites=fenics_test,
+gh workflow run system-tests-latest-components.yml -f suites=release
```
-To discover all tests, use `python print_test_suites.py`.
+More arguments are available, for example:
-To be able to fill in the right case tuple into the `tests.yaml`, you can use the `python3 print_case_combinations.py` script.
+```bash
+gh workflow run system-tests-latest-components.yml -f suites=release -f build_args="PLATFORM:ubuntu2404,PRECICE_REF:develop" -f log_level="DEBUG" --ref=develop
+```
-## Running the system tests on GitHub Actions
+The `build_args` override the defaults set in `tools/tests/components.yaml`.
-Go to Actions > [Run Testsuite (manual)](https://github.com/precice/tutorials/actions/workflows/run_testsuite_manual.yml) to see this workflow.
+### Running locally
-After bringing these changes to `master`, the manual triggering option should be visible on the top right. Until that happens, we can only trigger this workflow manually from the [GitHub CLI](https://github.blog/changelog/2021-04-15-github-cli-1-9-enables-you-to-work-with-github-actions-from-your-terminal/):
+To run locally, you will need Docker, Docker Compose, and Python 3.
-```shell
-gh workflow run run_testsuite_manual.yml -f suites=fenics_test --ref=develop
+Navigate into the directory `tools/tests/` of the tutorials, make a Python virtual environment, and install the dependencies:
+
+```bash
+python -m venv .venv && source .venv/bin/activate
+python -m pip install -r requirements.txt
```
-Another example, to use the latest releases and enable debug information of the tests:
+To test a certain test-suite defined in `tests.yaml`, use:
-```shell
-gh workflow run run_testsuite_manual.yml -f suites=fenics_test -f build_args="PRECICE_REF:v3.1.1,PRECICE_PRESET:production-audit,OPENFOAM_ADAPTER_REF:v1.3.0,PYTHON_BINDINGS_REF:v3.1.0,FENICS_ADAPTER_REF:v2.1.0,SU2_VERSION:7.5.1,SU2_ADAPTER_REF:64d4aff,DEALII_ADAPTER_REF:02c5d18,TUTORIALS_REF:340b447" -f log_level=DEBUG --ref=develop
+```bash
+python systemtests.py --suites=quickstart
```
-where the `*_REF` should be a specific [commit-ish](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefcommit-ishacommit-ishalsocommittish).
-
-Example output:
-
-```text
-Run cd tools/tests
- cd tools/tests
- python systemtests.py --build_args=PRECICE_REF:v3.1.1,PRECICE_PRESET:production-audit,OPENFOAM_ADAPTER_REF:v1.3.0,PYTHON_BINDINGS_REF:v3.1.0,FENICS_ADAPTER_REF:v2.1.0 --suites=fenics_test --log-level=DEBUG
- cd ../../
- shell: /usr/bin/bash -e {0}
-INFO: About to run the following systemtest in the directory /home/precice/runners_root/actions-runner-tutorial/_work/tutorials/tutorials/runs:
- [Flow over heated plate (fluid-openfoam, solid-fenics)]
-INFO: Started running Flow over heated plate (fluid-openfoam, solid-fenics), 0/1
-DEBUG: Checking out tutorials master before copying
-From https://github.com/precice/tutorials
- * [new branch] master -> master
-DEBUG: Building docker image for Flow over heated plate (fluid-openfoam, solid-fenics)
-DEBUG: Running tutorial Flow over heated plate (fluid-openfoam, solid-fenics)
-DEBUG: Running fieldcompare for Flow over heated plate (fluid-openfoam, solid-fenics)
-DEBUG: extracting /home/precice/runners_root/actions-runner-tutorial/_work/tutorials/tutorials/flow-over-heated-plate/reference-results/fluid-openfoam_solid-fenics.tar.gz into /home/precice/runners_root/actions-runner-tutorial/_work/tutorials/tutorials/runs/flow-over-heated-plate_fluid-openfoam-solid-fenics_2023-11-19-211723/reference_results
-Using log-level: DEBUG
-+---------------------------------------------------------+---------+-------------------+-----------------+-----------------------+
-| systemtest | success | building time [s] | solver time [s] | fieldcompare time [s] |
-CRITICAL: Fieldcompare returned non zero exit code, therefore Flow over heated plate (fluid-openfoam, solid-fenics) failed
-INFO: Running Flow over heated plate (fluid-openfoam, solid-fenics) took 280.5861554039875 seconds
-ERROR: Failed to run Flow over heated plate (fluid-openfoam, solid-fenics)
-+---------------------------------------------------------+---------+-------------------+-----------------+-----------------------+
-| Flow over heated plate (fluid-openfoam, solid-fenics) | 0 | 271.80 | 5.60 | 2.42 |
-+---------------------------------------------------------+---------+-------------------+-----------------+-----------------------+
+This will build and connect Docker containers and run tutorials in the `runs/` directory in the root of the tutorials.
+
+To clean up at the end, you might want to run a `docker system prune -a` and remove the `runs/` directory to save space.
+
+There are also some auxiliary scripts (run without arguments):
+
+- `print_test_suites.py`: Print all test suites defined in `tests.yaml`
+- `print_case_combinations.py`: Print all possible combinations of participants in a tutorial, using its `metadata.yaml`.
+
+## Understanding the logs
+
+For a local run, look into the `tutorials/runs/` directory, where you will find a time-stamped directory for every test executed.
+
+Each of these directories includes the usual tutorial case files and logs, as well as:
+
+1. `system-tests-build.log`: The logs of building the respective components.
+2. `system-tests-run.log`: The logs of running the simulation (intermixed, from all participants).
+3. `system-tests-compare.log`: The logs for the comparison to the reference results.
+
+In addition, in the directories of the cases executed, you can find `system-tests-.log` files.
+
+### Numerical regressions
+
+When the tests fail at the results comparison step, this typically means that there are numerical regressions (unless something wrong went undetected in a previous step). We use [fieldcompare](https://gitlab.com/dglaeser/fieldcompare) to compare all [preCICE exports](https://precice.org/configuration-export.html) to reference results generated from a previous run. Relevant files:
+
+- `precice-exports/`: The coupling meshes of the test run.
+- `reference-results/`: The coupling meshes of the reference run, as stored on Git LFS, expanded into `reference-results-unpacked`.
+- `diff-results/`: Numerical difference of the results in the two directories (computed with `fieldcompare dir --diff precice-exports/ reference/`). These are only present on failed comparisons.
+
+To reproduce the comparison locally, use the [same fieldcompare command](https://github.com/precice/tutorials/blob/develop/tools/tests/docker-compose.field_compare.template.yaml):
+
+```bash
+fieldcompare dir precice-exports/ reference-results-unpacked// \
+ --ignore-missing-reference-files \
+ --ignore-unsupported-file-formats \
+ -rtol 3e-7
```
-In this case, building and running seems to work out, but the tests fail because the results differ from the reference results. This may be incorrect, as the previous step may have silently failed.
+The differences are only shown per file, and there is no global metric or other summary (see [related discussion in fieldcompare](https://gitlab.com/dglaeser/fieldcompare/-/work_items/69)).
-## Understanding what went wrong
+Alternatively, [visualize the `precice-exports/diff_*.vtu` in ParaView](https://precice.org/configuration-export.html#visualization-with-paraview).
-The easiest way to debug a systemtest run is first to have a look at the output written into the action on GitHub.
-If this does not provide enough hints, the next step is to download the generated `system_tests_run__` artifact. Note that by default this will only be generated if the systemtests fail.
-Inside the archive, a test-specific subfolder like `flow-over-heated-plate_fluid-openfoam-solid-fenics_2023-11-19-211723` contains two log files: `system-tests-stderr.log` and `system-tests-stdout.log`. This can be a starting point for a further investigation. When fieldcompare runs with `--diff`, it writes VTK diff files under `precice-exports/`; if the comparison fails, those files are copied into a `diff-results/` subfolder in the same run directory (mirroring any subpaths under `precice-exports/`) so you can open them (e.g. in ParaView) to see where results differ from the reference. On successful comparisons, `diff-results/` is therefore absent.
+## Extending
-## Adding new tests
+### Adding new tests
-### Adding tutorials
+Tests and test suites are defined in [`tests.yaml`](https://github.com/precice/tutorials/blob/develop/tools/tests/tests.yaml). By convention, every tutorial defines a test suite with the same name as its directory, and several test cases using combinations of the available participants. These test cases are later referenced by other test suites: these are typically the `release` and the test suites of different tested components.
-In order for the systemtests to pick up the tutorial we need to define a `metadata.yaml` in the folder of the tutorial. There are a few `metadata.yaml` already present to get inspiration from. You can also have a look at the implementation details but normally the currently available ones should be easy to adopt. You can check your metadata parsing by `python print_metadata.py` and `python print_case_combinations.py`
+The available cases are listed in the `metadata.yaml` of each tutorial. To add a new tutorial case as a test, add it to `metadata.yaml` and then define a test using it. Include that test in the relevant test suites.
-### Adding testsuites
+Use the `max_time` or `max_time_windows` parameters to restrict the runtime of the test to the first few coupling time windows, to save time. Aim for a runtime of less than a minute (assuming cached components), if possible.
-To add a testsuite just open the `tests.yaml` file and use the output of `python print_case_combinations.py` to add the right case combinations you want to test. Note that you can specify a `reference_result` which is not yet present. The `generate_reference_data.py` will pick that up and create it for you.
-Note that its important to carefully check the paths of the `reference_result` in order to not have typos in there. Also note that same cases in different testsuites should use the same `reference_result`.
+You will need to define a reference results file. The reference results can and should be generated on GitHub using the [Generate reference results (manual)](https://github.com/precice/tutorials/actions/workflows/generate-reference-results-manual.yml) workflow for the respective test suite. You might want to temporarily set the `selected` test suite for requesting results only for a subset of test cases.
-To cap the preCICE simulation time for a specific test without editing `precice-config.xml`, add an optional `max_time` (positive float, overrides ``) or `max_time_windows` (positive integer, overrides ``) field to the tutorial entry. Applies to both test runs and reference result generation.
+Note that you will need to define the `TUTORIALS_REF` in the file [`reference_versions.yaml`](https://github.com/precice/tutorials/actions/workflows/generate-reference-results-manual.yml) to match the respective branch. Restore that to `develop` after that. See a [related issue](https://github.com/precice/tutorials/issues/844).
-### Generate reference results
+The results will be added to a Git LFS, but you will need special push access: just use the aforementioned GitHub Actions workflow, instead.
-Since we need data to compare against, you need to run `python generate_reference_data.py`. This process might take a while.
-Please include the generated reference results in the pull request as they are strongly connected to the new testsuites.
+### Adding new components
-## Adding repositories
+To add a new component, a few changes are needed:
-If you want to trigger a testsuite from a new repository, you need to add a workflow file to that repository (under `.github/workflows/`). You can, for example, copy and adjust [the one from the OpenFOAM adapter](https://github.com/precice/openfoam-adapter/blob/develop/.github/workflows/system-tests.yaml). Then, you need a new label to trigger the workflow (e.g. `Issues`->`Labels`->`New label`). Last, in the [preCICE organization settings](https://github.com/organizations/precice/settings), you need to add the new repository to the action secret `WORKFLOW_DISPATCH_TOKEN` and to the default actions runner group. Adding the new label directly to the pull request in which you add the workflow should already trigger the system tests, compare the [pull request in the `precice` repository](https://github.com/precice/precice/pull/2052).
+1. In the `components.yaml`, add a new component, defining all the parameters that it might need.
+ - Add these parameters into the `reference_versions.yaml`.
+ - Add fields for these parameters into the `system-tests-latest-components.yml` workflow.
+2. In the `dockerfiles//Dockerfile`, define a new stage for building your new component. Use the parameters you defined above.
+ - Defining a `_PR` variable will let you integrate the system tests into the respective component repository.
+3. In the `component_templates.yaml`, define a component template. These are Jinja templates that are used by Docker Compose, and the main detail is how to run a simulation using that component.
+4. Refer to the new component in the `metadata.yaml` of some tutorial and define some tests.
+
+### Adding new repositories that can trigger the tests
+
+If you want to trigger the system tests from a new repository:
+
+1. Add a workflow file to that repository (under `.github/workflows/`). Example: [OpenFOAM adapter](https://github.com/precice/openfoam-adapter/blob/develop/.github/workflows/system-tests.yaml).
+2. Create label as a trigger for workflow (under `Issues`->`Labels`->`New label`).
+3. Give permissions: In the [preCICE organization settings](https://github.com/organizations/precice/settings), you need to add the new repository to the action secret `WORKFLOW_DISPATCH_TOKEN` and to the default actions runner group. Adding the new label directly to the pull request in which you add the workflow should already trigger the system tests.
## Implementation details
-Each tutorial contains automation scripts (mainly `run.sh` and `clean.sh`), as well as metadata (`metadata.yaml`). The metadata file describes the available cases, how to run them, as well as their dependencies. A central `tests.yaml` file in this directory defines test suites, which execute different combinations of cases. The Python script `systemtests.py` executes the tests, allowing to filter for specific components or test suites.
+Each tutorial contains automation scripts (mainly `run.sh` and `clean.sh`), as well as metadata (`metadata.yaml`). The metadata file describes the available cases, how to run them, as well as their dependencies. A central `tests.yaml` file defines test suites, which execute different combinations of cases. The Python script `systemtests.py` executes the tests, filter for specific test suites.
+
+Read more about the system tests in the publication [System Regression Tests for the preCICE Coupling Ecosystem](https://doi.org/10.14279/eceasst.v83.2614).
+
+[](https://doi.org/10.14279/eceasst.v83.2614)
-Let's dive deeper into some of these aspects.
+Expand the implementation details...
### General architecture
@@ -145,15 +166,15 @@ Test steps include modifying the tutorial configuration files for the test syste
Tests are executed by the `systemtests.py` script, which starts the Docker Compose. This can be executed locally, and it is the same script that GitHub Actions also execute.
-The multi-stage Docker build allows building each component separately from the same Dockerfile, while Docker reuses cached layers. The Docker Compose services consider GitHub Actions Cache when building the services, although the cache is currently only updated, but not hit (see https://github.com/precice/tutorials/pull/372#issuecomment-1748335750).
+The multi-stage Docker build allows building each component separately from the same Dockerfile, while Docker reuses cached layers. The Docker Compose services consider GitHub Actions Cache when building the services, although the cache is currently only updated, but not hit (see https://github.com/precice/tutorials/pull/372#issuecomment-1748335750). For this reason, we are running on a dedicated self-hosted runner.
### File structure
Metadata and workflow/script files:
- `.github/workflows/`
- - `run_testsuite_workflow.yml`: workflow for running the tests, triggered by other workflows (e.g., other repositories)
- - `run_testsuite_manual.yml`: manual triggering front-end for `run_testsuite_workflow.yml`
+ - `system-tests.yml`: workflow for running the tests, triggered by other workflows (e.g., other repositories)
+ - `system-tests-latest-components.yml`: manual triggering front-end for `system-tests.yml`
- `flow-over-a-heated-plate/`
- `fluid-openfoam/`
- `run.sh`: describes how to execute the respective case
@@ -185,6 +206,38 @@ User-facing tools:
- `print_case_combinations.py`: Prints all possible combinations of tutorial cases, using the `metadata.yaml` files.
- `build_docker_images.py`: Build the Docker images for each test
- `generate_reference_results.py`: Executes the system tests with the versions defined in `reference_versions.yaml` and generates the reference data archives, with the names described in `tests.yaml`. (should only be used by the CI Pipeline)
+ - `update_requirements_reference.py`: Regenerates `requirements-reference.txt` with pinned Python versions from `reference_versions.yaml` (for reproducibility, see issue #610).
+ - `validate_requirements_reference.py`: Validates that `requirements-reference.txt` exists and pyprecice version matches `reference_versions.yaml`.
+
+### requirements-reference.txt
+
+A lockfile-style list of pinned Python dependency versions (pyprecice, numpy, matplotlib, nutils, setuptools) for reproducible builds and distributions (see issue [#610](https://github.com/precice/tutorials/issues/610)). This file is a **reference manifest only**: tutorial `run.sh` scripts keep using their own `requirements.txt` (with loose constraints) to avoid merge back-and-forth; system tests use the Docker image’s venv. The reference file records “versions known to work” for a distribution.
+
+**Update at each release.** For best accuracy (match what CI uses), capture from the systemtest Docker image:
+
+```bash
+docker run --rm pip freeze | python3 update_requirements_reference.py --from-freeze
+```
+
+Or regenerate from `reference_versions.yaml` only (pyprecice from PYTHON_BINDINGS_REF; others from script defaults):
+
+```bash
+cd tools/tests
+python3 update_requirements_reference.py
+```
+
+### Tutorial Python dependencies (issue [#610](https://github.com/precice/tutorials/issues/610))
+
+Each Python-based tutorial case has a `requirements.txt` with **loose version constraints** (e.g. `numpy >1, <2`, `pyprecice~=3.0`) so the latest compatible packages can be installed during development.
+
+For **distribution releases**, regenerate the root-level `requirements-reference.txt` lockfile manifest. This records the latest PyPI versions that satisfy each tutorial's constraints at release time, without pinning every tutorial file:
+
+```bash
+pip install packaging
+python3 tools/report_tutorial_requirements.py
+```
+
+CI validates the reference file with `python3 tools/validate_requirements_reference.py` (or `--check` on the report script).
Implementation scripts:
@@ -244,47 +297,43 @@ Description:
### Components
-The components mentioned in the Metadata are defined in the central `components.yaml` file. This file also specifies some arguments and their default values. These arguments can be anything, but most often they are version-related information. For example, the version of the OpenFOAM library used by the openfoam-adapter component, or the openfoam-adapter component version itself. For example:
+The components mentioned in the Metadata are defined in the central `components.yaml` file. This file also specifies some arguments and their default values. These arguments can be anything, but most often they are version-related information. For example, the version of OpenFOAM used by the openfoam-adapter component, or the component version itself. For example:
```yaml
openfoam-adapter:
- repository: https://github.com/precice/openfoam-adapter
template: component-templates/openfoam-adapter.yaml
build_arguments:
+ PLATFORM:
+ default: "ubuntu_2404"
PRECICE_REF:
- description: Version of preCICE to use
- default: "main"
+ repository: https://github.com/precice/precice
+ default: "develop"
PRECICE_PRESET:
- description: CMake preset of preCICE
default: "production-audit"
- PLATFORM:
- description: Dockerfile platform used
- default: "ubuntu_2404"
TUTORIALS_REF:
- description: Tutorial git reference to use
- default: "master"
+ repository: https://github.com/precice/tutorials
+ default: "develop"
OPENFOAM_EXECUTABLE:
- description: exectuable of openfoam to use
default: "openfoam2512"
OPENFOAM_ADAPTER_REF:
- description: Reference/tag of the actual OpenFOAM adapter
- default: "master"
+ repository: https://github.com/precice/openfoam-adapter
+ default: "develop"
```
This `openfoam-adapter` component has the following attributes:
-- `repository`: URL to the Git projects
- `template`: A template for a Docker Compose service of this component
- `build_arguments`: Arguments passed to the Docker Compose service (arbitrary)
#### Naming schema for build_arguments
-Since the docker containers are still a bit mixed in terms of capabilities and support for different build_argument combinations the following rules apply:
+The following rules apply for the `build_arguments`:
-- A build argument ending in `_REF` refers to a git commit-ish (like a tag or commit) being used to build the image. It is important to not use branch names here as we heavily rely on Docker's build cache to speedup things. But since the input variable to the docker builder will not change, we might have wrong cache hits.
-- Some workflows set variables ending in `_PR`. These specify the GitHub pull request which provides the above `_REF` and can be on a fork.
+- A build argument ending in `_REF` refers to a git commit-ish (like a tag or commit) being used to build the image.
+- The `repository` parameter of any `_REF` argument points to the repository where the respective Git reference should be resolved. This is assumed to be consistent across components and the Dockerfile (and could be simplified).
+- Some workflows set variables ending in `_PR`. These specify the GitHub pull request, which provides the above `_REF` and can be on a fork.
- A build argument ending in `_VERSION` refers to the version of a third-party dependency to use (e.g., DUNE).
-- All other build_arguments are free of rules and up to the container maintainer.
+- All other `build_arguments` are free of rules and up to the container maintainer.
### Component templates
@@ -305,61 +354,15 @@ command: >
This template defines:
-- `image`: The base Docker image for this component, including a Git reference (tag), provided to the template as argument (e.g., by the `systemtests.py` script).
+- `image`: The base Docker image for this component, including a Git reference (tag), provided to the template as an argument (e.g., by the `systemtests.py` script).
- `depends_on`: Other services this service depends upon, typically a preparation service that fetches all components and tutorials.
- `volumes`: Directories mapped between the host and the container. Apart from directories relating to the users and groups, this also defines where to run the cases.
- `command`: How to run a case depending on this component, including how and where to redirect any screen output.
-### Tests
-
-Concrete tests are specified centrally in the file `tests.yaml`. For example:
-
-```yaml
-test_suites:
- openfoam_adapter_pr:
- tutorials:
- - path: flow-over-heated-plate
- case_combination:
- - fluid-openfoam
- - solid-openfoam
- reference_result: ./flow-over-heated-plate/reference-results/fluid-openfoam_solid-openfoam.tar.gz
- openfoam_adapter_release:
- tutorials:
- - path: flow-over-heated-plate
- case_combination:
- - fluid-openfoam
- - solid-openfoam
- reference_result: ./flow-over-heated-plate/reference-results/fluid-openfoam_solid-openfoam.tar.gz
- - path: flow-over-heated-plate
- case_combination:
- - fluid-openfoam
- - solid-fenics
- reference_result: ./flow-over-heated-plate/reference-results/fluid-openfoam_solid-fenics.tar.gz
- timeout: 1200
-```
-
-The optional `timeout` field (in seconds) sets the maximum time for the solver run and fieldcompare phases of that specific case. If omitted, it defaults to `GLOBAL_TIMEOUT` (currently 900s, overridable via the `PRECICE_SYSTEMTESTS_TIMEOUT` environment variable).
-
-This defines two test suites, namely `openfoam_adapter_pr` and `openfoam_adapter_release`. Each of them defines which case combinations of which tutorials to run.
-
-### Generate Reference Results
-
-#### via GitHub workflow (recommended)
-
-The preferred way of adding reference results is via the manual `Generate reference results (manual)` workflow. This takes two inputs:
-
-- `from_ref`: branch where the new test configuration (e.g added tests, new reference_versions.yaml) is
-- `commit_msg`: commit message for adding the reference results into the branch
-
-The workflow will checkout the `from_ref`, take the status of the systemtests of that branch and execute `python generate_reference_results.py`, upload the LFS objects into the self-hosted LFS server and add a commit with `commit_msg` onto the `from_ref` branch.
-
-#### manually
+### Timeouts
-In order to generate the reference results edit the `reference_versions.yaml` to match the required `build_arguments` otherwise passed via the cli.
-Executing `generate_reference_results.py` will then generate the following files:
+A `GLOBAL_TIMEOUT` is used for all operations. Its default value is 600s (5min), it is set in the beginning of [`Systemtests.py`](https://github.com/precice/tutorials/blob/develop/tools/tests/systemtests/Systemtest.py), and it can be overridden via the `PRECICE_SYSTEMTESTS_TIMEOUT` environment variable.
-- all distinct `.tar.gz` defined in the `tests.yaml`
-- a `reference_results.md` in the tutorial folder describing the arguments used and a sha-1 hash of the `tar.gz` archive.
+Tests can define a different `timeout` in their `tests.yaml` entry, which applies to the running and results comparison steps.
-The reference result archive will later be unpacked again during the systemtest and compared using `fieldcompare`
-Please note that these files should always be kept in the git lfs.
+
diff --git a/tools/tests/build_docker_images.py b/tools/tests/build_docker_images.py
index 4cb34e252..da1df5a5f 100644
--- a/tools/tests/build_docker_images.py
+++ b/tools/tests/build_docker_images.py
@@ -19,12 +19,12 @@ def main():
parser.add_argument(
'--build_args',
type=str,
- help='Comma-separated list of arguments provided to the components like openfoam:2102,pythonbindings:latest')
+ help='Comma-separated list of component build arguments (e.g., "PRECICE_REF:develop,OPENFOAM_ADAPTER_REF:develop")')
parser.add_argument('--rundir', type=str, help='Directory to run the systemstests in.',
nargs='?', const=PRECICE_TESTS_RUN_DIR, default=PRECICE_TESTS_RUN_DIR)
- parser.add_argument('--log-level', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
- default='INFO', help='Set the logging level')
+ parser.add_argument('--log_level', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
+ default='INFO', help='Set the logging level of the system tests scripts.')
# Parse the command-line arguments
args = parser.parse_args()
@@ -32,7 +32,7 @@ def main():
# Configure logging based on the provided log level
logging.basicConfig(level=args.log_level, format='%(levelname)s: %(message)s')
- print(f"Using log-level: {args.log_level}")
+ print(f"Using log_level: {args.log_level}")
systemtests_to_run = []
available_tutorials = Tutorials.from_path(PRECICE_TUTORIAL_DIR)
diff --git a/tools/tests/component-templates/fenics-adapter.yaml b/tools/tests/component-templates/fenics-adapter.yaml
index 220a52525..37f70f5a6 100644
--- a/tools/tests/component-templates/fenics-adapter.yaml
+++ b/tools/tests/component-templates/fenics-adapter.yaml
@@ -13,4 +13,6 @@ volumes:
command: >
/bin/bash -c "id &&
cd '/runs/{{ tutorial_folder }}/{{ case_folder }}' &&
- {{ run }} | tee system-tests_{{ case_folder }}.log 2>&1"
+ {{ run }} &&
+ rm -rf .venv __pycache__
+ | tee system-tests_{{ case_folder }}.log 2>&1"
diff --git a/tools/tests/component-templates/fenicsx-adapter.yaml b/tools/tests/component-templates/fenicsx-adapter.yaml
new file mode 100644
index 000000000..3125f0ff1
--- /dev/null
+++ b/tools/tests/component-templates/fenicsx-adapter.yaml
@@ -0,0 +1,18 @@
+build:
+ context: {{ dockerfile_context }}
+ args:
+ {% for key, value in build_arguments.items() %}
+ - {{key}}={{value}}
+ {% endfor %}
+ target: fenicsx_adapter
+depends_on:
+ prepare:
+ condition: service_completed_successfully
+volumes:
+ - {{ run_directory }}:/runs
+command: >
+ /bin/bash -c "id &&
+ cd '/runs/{{ tutorial_folder }}/{{ case_folder }}' &&
+ {{ run }} &&
+ rm -rf .venv __pycache__
+ | tee system-tests_{{ case_folder }}.log 2>&1"
diff --git a/tools/tests/component-templates/mercurydpm-adapter.yaml b/tools/tests/component-templates/mercurydpm-adapter.yaml
new file mode 100644
index 000000000..ac085d079
--- /dev/null
+++ b/tools/tests/component-templates/mercurydpm-adapter.yaml
@@ -0,0 +1,16 @@
+build:
+ context: {{ dockerfile_context }}
+ args:
+ {% for key, value in build_arguments.items() %}
+ - {{key}}={{value}}
+ {% endfor %}
+ target: mercurydpm_adapter
+depends_on:
+ prepare:
+ condition: service_completed_successfully
+volumes:
+ - {{ run_directory }}:/runs
+command: >
+ /bin/bash -c "id &&
+ cd '/runs/{{ tutorial_folder }}/{{ case_folder }}' &&
+ {{ run }} | tee system-tests_{{ case_folder }}.log 2>&1"
diff --git a/tools/tests/component-templates/micro-manager.yaml b/tools/tests/component-templates/micro-manager.yaml
index 1a78a1b4b..35c41e400 100644
--- a/tools/tests/component-templates/micro-manager.yaml
+++ b/tools/tests/component-templates/micro-manager.yaml
@@ -13,4 +13,6 @@ volumes:
command: >
/bin/bash -c "id &&
cd '/runs/{{ tutorial_folder }}/{{ case_folder }}' &&
- {{ run }} | tee system-tests_{{ case_folder }}.log 2>&1"
+ {{ run }} &&
+ rm -rf .venv __pycache__
+ | tee system-tests_{{ case_folder }}.log 2>&1"
diff --git a/tools/tests/component-templates/nutils-adapter.yaml b/tools/tests/component-templates/nutils-adapter.yaml
index 5893c65a7..e8abbc066 100644
--- a/tools/tests/component-templates/nutils-adapter.yaml
+++ b/tools/tests/component-templates/nutils-adapter.yaml
@@ -13,4 +13,6 @@ volumes:
command: >
/bin/bash -c "id &&
cd '/runs/{{ tutorial_folder }}/{{ case_folder }}' &&
- {{ run }} | tee system-tests_{{ case_folder }}.log 2>&1"
+ {{ run }} &&
+ rm -rf .venv __pycache__
+ | tee system-tests_{{ case_folder }}.log 2>&1"
diff --git a/tools/tests/component-templates/python-bindings.yaml b/tools/tests/component-templates/python-bindings.yaml
index 3cd65d274..3ea7ad8d0 100644
--- a/tools/tests/component-templates/python-bindings.yaml
+++ b/tools/tests/component-templates/python-bindings.yaml
@@ -13,4 +13,6 @@ volumes:
command: >
/bin/bash -c "id &&
cd '/runs/{{ tutorial_folder }}/{{ case_folder }}' &&
- {{ run }} | tee system-tests_{{ case_folder }}.log 2>&1"
+ {{ run }} &&
+ rm -rf .venv __pycache__
+ | tee system-tests_{{ case_folder }}.log 2>&1"
diff --git a/tools/tests/component-templates/su2-adapter.yaml b/tools/tests/component-templates/su2-adapter.yaml
index d466a949a..5a7abd8d0 100644
--- a/tools/tests/component-templates/su2-adapter.yaml
+++ b/tools/tests/component-templates/su2-adapter.yaml
@@ -13,4 +13,6 @@ volumes:
command: >
/bin/bash -c "id &&
cd '/runs/{{ tutorial_folder }}/{{ case_folder }}' &&
- SU2_RUN="/home/precice/SU2_RUN/bin" PYTHONPATH="/home/precice/SU2_RUN/bin:$PYTHONPATH" {{ run }} | tee system-tests_{{ case_folder }}.log 2>&1"
+ SU2_RUN="/home/precice/SU2_RUN/bin" PYTHONPATH="/home/precice/SU2_RUN/bin:$PYTHONPATH" {{ run }} &&
+ rm -rf .venv __pycache__
+ | tee system-tests_{{ case_folder }}.log 2>&1"
diff --git a/tools/tests/components.yaml b/tools/tests/components.yaml
index d8498fd88..c7a4de2b0 100644
--- a/tools/tests/components.yaml
+++ b/tools/tests/components.yaml
@@ -1,214 +1,213 @@
bare: # A default component used when the solver does not have any dependencies apart from preCICE itself
- repository: https://github.com/precice/precice
template: component-templates/bare.yaml
build_arguments: # these things mean something to the docker-service
PLATFORM:
- description: Dockerfile platform used
default: "ubuntu_2404"
PRECICE_REF:
- description: Version of preCICE to use
- default: "main"
+ repository: https://github.com/precice/precice
+ default: "develop"
PRECICE_PRESET:
- description: CMake preset of preCICE
default: "production-audit"
TUTORIALS_REF:
- description: Tutorial git reference to use
- default: "master"
+ repository: https://github.com/precice/tutorials
+ default: "develop"
-python-bindings:
- repository: https://github.com/precice/python-bindings
- template: component-templates/python-bindings.yaml
+calculix-adapter:
+ template: component-templates/calculix-adapter.yaml
build_arguments:
PLATFORM:
- description: Dockerfile platform used
default: "ubuntu_2404"
PRECICE_REF:
- description: Version of preCICE to use
- default: "main"
+ repository: https://github.com/precice/precice
+ default: "develop"
PRECICE_PRESET:
- description: CMake preset of preCICE
default: "production-audit"
TUTORIALS_REF:
- description: Tutorial git reference to use
- default: "master"
- PYTHON_BINDINGS_REF:
- description: Git ref of the Python bindings to use
- default: "master"
+ repository: https://github.com/precice/tutorials
+ default: "develop"
+ CALCULIX_VERSION:
+ default: "2.20"
+ CALCULIX_ADAPTER_REF:
+ repository: https://github.com/precice/calculix-adapter
+ default: "develop"
-openfoam-adapter:
- repository: https://github.com/precice/openfoam-adapter
- template: component-templates/openfoam-adapter.yaml
+dealii-adapter:
+ template: component-templates/dealii-adapter.yaml
build_arguments:
PLATFORM:
- description: Dockerfile platform used
default: "ubuntu_2404"
PRECICE_REF:
- description: Version of preCICE to use
- default: "main"
+ repository: https://github.com/precice/precice
+ default: "develop"
PRECICE_PRESET:
- description: CMake preset of preCICE
default: "production-audit"
TUTORIALS_REF:
- description: Tutorial git reference to use
- default: "master"
- OPENFOAM_EXECUTABLE:
- description: exectuable of openfoam to use
- default: "openfoam2512"
- OPENFOAM_ADAPTER_REF:
- description: Reference/tag of the OpenFOAM adapter to use
- default: "master"
+ repository: https://github.com/precice/tutorials
+ default: "develop"
+ DEALII_ADAPTER_REF:
+ repository: https://github.com/precice/dealii-adapter
+ default: "develop"
+
+dumux-adapter:
+ template: component-templates/dumux-adapter.yaml
+ build_arguments:
+ PLATFORM:
+ default: "ubuntu_2404"
+ PRECICE_REF:
+ repository: https://github.com/precice/precice
+ default: "develop"
+ PRECICE_PRESET:
+ default: "production-audit"
+ TUTORIALS_REF:
+ repository: https://github.com/precice/tutorials
+ default: "develop"
+ DUNE_VERSION:
+ default: "2.9"
+ DUMUX_VERSION:
+ default: "3.7"
+ DUMUX_ADAPTER_REF:
+ repository: https://github.com/precice/dumux-adapter
+ default: "develop"
fenics-adapter:
- repository: https://github.com/precice/fenics-adapter
template: component-templates/fenics-adapter.yaml
build_arguments:
PLATFORM:
- description: Dockerfile platform used
default: "ubuntu_2404"
PRECICE_REF:
- description: Version of preCICE to use
- default: "main"
+ repository: https://github.com/precice/precice
+ default: "develop"
PRECICE_PRESET:
- description: CMake preset of preCICE
default: "production-audit"
TUTORIALS_REF:
- description: Tutorial git reference to use
- default: "master"
+ repository: https://github.com/precice/tutorials
+ default: "develop"
PYTHON_BINDINGS_REF:
- description: Git ref of the Python bindings to use
- default: "master"
+ repository: https://github.com/precice/python-bindings
+ default: "develop"
FENICS_ADAPTER_REF:
- description: Git ref of the fenics adapter to use
- default: "master"
+ repository: https://github.com/precice/fenics-adapter
+ default: "develop"
-nutils-adapter:
- repository: https://github.com/precice/nutils-adapter
- template: component-templates/nutils-adapter.yaml
+fenicsx-adapter:
+ template: component-templates/fenicsx-adapter.yaml
build_arguments:
PLATFORM:
- description: Dockerfile platform used
default: "ubuntu_2404"
PRECICE_REF:
- description: Version of preCICE to use
- default: "main"
+ repository: https://github.com/precice/precice
+ default: "develop"
PRECICE_PRESET:
- description: CMake preset of preCICE
default: "production-audit"
TUTORIALS_REF:
- description: Tutorial git reference to use
- default: "master"
+ repository: https://github.com/precice/tutorials
+ default: "develop"
PYTHON_BINDINGS_REF:
- description: Git ref of the Python bindings to use
- default: "master"
+ repository: https://github.com/precice/python-bindings
+ default: "develop"
+ FENICSX_ADAPTER_REF:
+ repository: https://github.com/precice/fenicsx-adapter
+ default: "develop"
-calculix-adapter:
- repository: https://github.com/precice/calculix-adapter
- template: component-templates/calculix-adapter.yaml
+mercurydpm-adapter:
+ template: component-templates/mercurydpm-adapter.yaml
build_arguments:
PLATFORM:
- description: Dockerfile platform used
default: "ubuntu_2404"
PRECICE_REF:
- description: Version of preCICE to use
- default: "main"
+ repository: https://github.com/precice/precice
+ default: "develop"
PRECICE_PRESET:
- description: CMake preset of preCICE
default: "production-audit"
TUTORIALS_REF:
- description: Tutorial git reference to use
- default: "master"
- CALCULIX_VERSION:
- description: Version of Calculix to use
- default: "2.20"
- CALCULIX_ADAPTER_REF:
- description: Version of Calculix-Adapter to use
- default: "master"
+ repository: https://github.com/precice/tutorials
+ default: "develop"
-su2-adapter:
- repository: https://github.com/precice/su2-adapter
- template: component-templates/su2-adapter.yaml
+micro-manager:
+ template: component-templates/micro-manager.yaml
build_arguments:
PLATFORM:
- description: Dockerfile platform used
default: "ubuntu_2404"
PRECICE_REF:
- description: Version of preCICE to use
- default: "main"
+ repository: https://github.com/precice/precice
+ default: "develop"
PRECICE_PRESET:
- description: CMake preset of preCICE
default: "production-audit"
TUTORIALS_REF:
- description: Tutorial git reference to use
- default: "master"
- SU2_VERSION:
- description: Version of SU2 to use
- default: "7.5.1"
- SU2_ADAPTER_REF:
- description: Version of SU2-Adapter to use
- default: "master"
+ repository: https://github.com/precice/tutorials
+ default: "develop"
+ MICRO_MANAGER_REF:
+ repository: https://github.com/precice/micro-manager
+ default: "develop"
-dealii-adapter:
- repository: https://github.com/precice/dealii-adapter
- template: component-templates/dealii-adapter.yaml
+nutils-adapter:
+ template: component-templates/nutils-adapter.yaml
build_arguments:
PLATFORM:
- description: Dockerfile platform used
default: "ubuntu_2404"
PRECICE_REF:
- description: Version of preCICE to use
- default: "main"
+ repository: https://github.com/precice/precice
+ default: "develop"
PRECICE_PRESET:
- description: CMake preset of preCICE
default: "production-audit"
TUTORIALS_REF:
- description: Tutorial git reference to use
- default: "master"
- DEALII_ADAPTER_REF:
- description: Version of deal.ii-adapter to use
- default: "master"
+ repository: https://github.com/precice/tutorials
+ default: "develop"
+ PYTHON_BINDINGS_REF:
+ repository: https://github.com/precice/python-bindings
+ default: "develop"
-dumux-adapter:
- repository: https://github.com/precice/dumux-adapter
- template: component-templates/dumux-adapter.yaml
+openfoam-adapter:
+ template: component-templates/openfoam-adapter.yaml
build_arguments:
PLATFORM:
- description: Dockerfile platform used
default: "ubuntu_2404"
PRECICE_REF:
- description: Version of preCICE to use
- default: "main"
+ repository: https://github.com/precice/precice
+ default: "develop"
PRECICE_PRESET:
- description: CMake preset of preCICE
default: "production-audit"
TUTORIALS_REF:
- description: Tutorial git reference to use
- default: "master"
- DUNE_VERSION:
- description: Version of DUNE to use
- default: "2.9"
- DUMUX_VERSION:
- description: Version of DuMux to use
- default: "3.7"
- DUMUX_ADAPTER_REF:
- description: Git ref of the dumux adapter to use
- default: "main"
+ repository: https://github.com/precice/tutorials
+ default: "develop"
+ OPENFOAM_EXECUTABLE:
+ default: "openfoam2512"
+ OPENFOAM_ADAPTER_REF:
+ repository: https://github.com/precice/openfoam-adapter
+ default: "develop"
-micro-manager:
- repository: https://github.com/precice/micro-manager
- template: component-templates/micro-manager.yaml
+python-bindings:
+ template: component-templates/python-bindings.yaml
build_arguments:
PLATFORM:
- description: Dockerfile platform used
default: "ubuntu_2404"
PRECICE_REF:
- description: Version of preCICE to use
- default: "main"
+ repository: https://github.com/precice/precice
+ default: "develop"
PRECICE_PRESET:
- description: CMake preset of preCICE
default: "production-audit"
TUTORIALS_REF:
- description: Tutorial git reference to use
- default: "master"
- MICRO_MANAGER_REF:
- description: Version of Micro-Manager to use
- default: "0.8.0"
+ repository: https://github.com/precice/tutorials
+ default: "develop"
+ PYTHON_BINDINGS_REF:
+ repository: https://github.com/precice/python-bindings
+ default: "develop"
+
+su2-adapter:
+ template: component-templates/su2-adapter.yaml
+ build_arguments:
+ PLATFORM:
+ default: "ubuntu_2404"
+ PRECICE_REF:
+ repository: https://github.com/precice/precice
+ default: "develop"
+ PRECICE_PRESET:
+ default: "production-audit"
+ TUTORIALS_REF:
+ repository: https://github.com/precice/tutorials
+ default: "develop"
+ SU2_VERSION:
+ default: "7.5.1"
+ SU2_ADAPTER_REF:
+ repository: https://github.com/precice/su2-adapter
+ default: "develop"
diff --git a/tools/tests/docker-compose.template.yaml b/tools/tests/docker-compose.template.yaml
index 1eaddbeee..534e952c0 100644
--- a/tools/tests/docker-compose.template.yaml
+++ b/tools/tests/docker-compose.template.yaml
@@ -13,7 +13,7 @@ services:
/bin/bash -c "id &&
cd '/runs/{{ tutorial_folder }}' &&
sed -i 's||= debug and %Rank% = 0\" enabled=\"true\" />|g' precice-config.xml &&
- sed -i 's%% %g' precice-config.xml &&
+ sed -i 's%% %g' precice-config.xml &&
sed -i 's|m2n:sockets |m2n:sockets network=\"eth0\" |g' precice-config.xml &&
cat precice-config.xml"
diff --git a/tools/tests/dockerfiles/ubuntu_2404/Dockerfile b/tools/tests/dockerfiles/ubuntu_2404/Dockerfile
index f9aabd4c4..a1f0eb74a 100644
--- a/tools/tests/dockerfiles/ubuntu_2404/Dockerfile
+++ b/tools/tests/dockerfiles/ubuntu_2404/Dockerfile
@@ -38,7 +38,7 @@ USER precice
FROM base_image AS precice_dependecies
USER root
-# Installing necessary dependecies for preCICE
+# Dependencies for preCICE and common dependencies for the tutorials/tests
RUN apt-get -qq update && \
apt-get -qq -y install \
build-essential \
@@ -61,7 +61,16 @@ RUN apt-get -qq update && \
python3-pip \
python3-venv \
pkg-config \
- wget
+ wget \
+ inotify-tools
+# The following are dependencies of gmsh, needed by some tutorials
+RUN apt-get -qq update && \
+ apt-get -qq install \
+ libglu1-mesa \
+ libxrender1 \
+ libxcursor1 \
+ libxft2 \
+ libxinerama1
USER precice
FROM precice_dependecies AS precice
@@ -125,6 +134,18 @@ RUN python3 -m venv --system-site-packages /home/precice/venv && \
. /home/precice/venv/bin/activate && \
pip3 install git+https://github.com/precice/fenics-adapter.git@${FENICS_ADAPTER_REF}
+FROM precice_dependecies AS fenicsx_adapter
+COPY --from=python_bindings /home/precice/.local /home/precice/.local
+USER root
+RUN add-apt-repository -y ppa:fenics-packages/fenics && \
+ apt-get -qq update && \
+ apt-get -qq install --no-install-recommends fenicsx
+USER precice
+ARG FENICSX_ADAPTER_REF
+# Building fenicsx-adapter
+RUN python3 -m venv --system-site-packages /home/precice/venv && \
+ . /home/precice/venv/bin/activate && \
+ pip3 install git+https://github.com/precice/fenicsx-adapter.git@${FENICSX_ADAPTER_REF}
FROM precice_dependecies AS nutils_adapter
COPY --from=python_bindings /home/precice/.local /home/precice/.local
@@ -210,6 +231,19 @@ RUN git clone https://github.com/precice/dealii-adapter.git &&\
cmake . && \
make -j $(nproc)
+FROM precice_dependecies AS mercurydpm_adapter
+USER precice
+COPY --from=precice /home/precice/.local /home/precice/.local
+WORKDIR /home/precice
+ENV PATH="/home/precice/mercurydpm/build/Drivers/PreCICE:$PATH"
+# The channel-transport-particles tutorial is hosted in a frozen fork of the MercuryDPM repository.
+# That's why there are no arguments for version, ref, or pr.
+RUN git clone https://bitbucket.org/davidscn/mercurydpm.git &&\
+ cd mercurydpm && \
+ git checkout channel-transport-tutorial && \
+ mkdir -p build && cd build && \
+ cmake -D MercuryDPM_PreCICE_COUPLING="ON" .. && \
+ make -j $(nproc) ChannelTransport
FROM precice_dependecies AS micro_manager
USER precice
diff --git a/tools/tests/generate_reference_results.py b/tools/tests/generate_reference_results.py
index a9bac5ac1..d7470c8a6 100644
--- a/tools/tests/generate_reference_results.py
+++ b/tools/tests/generate_reference_results.py
@@ -89,14 +89,14 @@ def main():
parser.add_argument('--suites', type=str,
help='Comma-separated test suites to generate reference results for. '
'If not specified, all suites are used.')
- parser.add_argument('--log-level', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
+ parser.add_argument('--log_level', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
default='INFO', help='Set the logging level')
args = parser.parse_args()
logging.basicConfig(level=args.log_level, format='%(levelname)s: %(message)s')
- print(f"Using log-level: {args.log_level}")
+ print(f"Using log_level: {args.log_level}")
run_directory = Path(args.rundir)
diff --git a/tools/tests/metadata_parser/metdata.py b/tools/tests/metadata_parser/metdata.py
index 75b5bb425..1c9b98d55 100644
--- a/tools/tests/metadata_parser/metdata.py
+++ b/tools/tests/metadata_parser/metdata.py
@@ -11,8 +11,8 @@
class BuildArgument:
"""Represents a BuildArgument needed to run the docker container"""
- description: str
- """The description of the parameter."""
+ repository: str
+ """The repository corresponging to a _REF parameter."""
key: str
"""The name of the parameter."""
@@ -61,15 +61,14 @@ def from_components_yaml(cls, data):
"""
arguments = []
for argument_name, argument_dict in data['build_arguments'].items():
- # TODO maybe **params
- description = argument_dict.get(
- 'description', f"No description provided for {argument_name}")
+ repository = argument_dict.get(
+ 'repository', f"No repository provided for {argument_name}")
key = argument_name
default = argument_dict.get('default', None)
value_options = argument_dict.get('value_options', None)
arguments.append(BuildArgument(
- description, key, value_options, default))
+ repository, key, value_options, default))
return cls(arguments)
@@ -97,7 +96,6 @@ class Component:
name: str
template: str
- repository: str
parameters: BuildArguments
def __eq__(self, other):
@@ -134,10 +132,9 @@ def from_yaml(cls, path):
for component_name in data:
parameters = BuildArguments.from_components_yaml(
data[component_name])
- repository = data[component_name]["repository"]
template = data[component_name]["template"]
components.append(
- Component(component_name, template, repository, parameters))
+ Component(component_name, template, parameters))
return cls(components)
diff --git a/tools/tests/print_case_combinations.py b/tools/tests/print_case_combinations.py
index 25e318918..a891209e0 100644
--- a/tools/tests/print_case_combinations.py
+++ b/tools/tests/print_case_combinations.py
@@ -8,14 +8,14 @@
def main():
parser = argparse.ArgumentParser(description='Prints available Metadata for tutorials')
- parser.add_argument('--log-level', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
+ parser.add_argument('--log_level', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
default='INFO', help='Set the logging level')
args = parser.parse_args()
# Configure logging based on the provided log level
logging.basicConfig(level=args.log_level, format='%(levelname)s: %(message)s')
- print(f"Using log-level: {args.log_level}")
+ print(f"Using log_level: {args.log_level}")
available_tutorials = Tutorials.from_path(PRECICE_TUTORIAL_DIR)
diff --git a/tools/tests/print_metadata.py b/tools/tests/print_metadata.py
index 500e549c9..9ed7a3648 100644
--- a/tools/tests/print_metadata.py
+++ b/tools/tests/print_metadata.py
@@ -7,14 +7,14 @@
def main():
parser = argparse.ArgumentParser(description='Prints available Metadata for tutorials')
- parser.add_argument('--log-level', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
+ parser.add_argument('--log_level', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
default='INFO', help='Set the logging level')
args = parser.parse_args()
# Configure logging based on the provided log level
logging.basicConfig(level=args.log_level, format='%(levelname)s: %(message)s')
- print(f"Using log-level: {args.log_level}")
+ print(f"Using log_level: {args.log_level}")
available_tutorials = Tutorials.from_path(PRECICE_TUTORIAL_DIR)
print("Fount the following tutorials read from the metadata.yaml")
diff --git a/tools/tests/print_test_suites.py b/tools/tests/print_test_suites.py
index 6fc1e4039..14d69ef2b 100644
--- a/tools/tests/print_test_suites.py
+++ b/tools/tests/print_test_suites.py
@@ -9,14 +9,14 @@
def main():
parser = argparse.ArgumentParser(description='Prints available Test Suites')
- parser.add_argument('--log-level', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
+ parser.add_argument('--log_level', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
default='INFO', help='Set the logging level')
args = parser.parse_args()
# Configure logging based on the provided log level
logging.basicConfig(level=args.log_level, format='%(levelname)s: %(message)s')
- print(f"Using log-level: {args.log_level}")
+ print(f"Using log_level: {args.log_level}")
available_tutorials = Tutorials.from_path(PRECICE_TUTORIAL_DIR)
available_testsuites = TestSuites.from_yaml(
diff --git a/tools/tests/reference_versions.yaml b/tools/tests/reference_versions.yaml
index 55e2b0396..6c7e69563 100644
--- a/tools/tests/reference_versions.yaml
+++ b/tools/tests/reference_versions.yaml
@@ -1,17 +1,28 @@
-PRECICE_REF: "d199bb3" # develop, January 20, 2026
-PRECICE_PRESET: "production-audit"
-OPENFOAM_EXECUTABLE: "openfoam2312"
-OPENFOAM_ADAPTER_REF: "v1.3.1"
-PYTHON_BINDINGS_REF: "v3.2.0"
-FENICS_ADAPTER_REF: "v2.2.0"
-TUTORIALS_REF: "b18b3ef" # May 10, 2026, https://github.com/precice/tutorials/pull/769
+# Versions used by the generate_reference_results.py script,
+# and default values for unspecified values in systemtests.py.
+
+# Dockerfile used (See dockerfiles/)
PLATFORM: "ubuntu_2404"
+
+# Third-party dependencies
CALCULIX_VERSION: "2.20"
-CALCULIX_ADAPTER_REF: "v2.20.1"
-SU2_VERSION: "7.5.1"
-SU2_ADAPTER_REF: "64d4aff" # Distribution v2404
-DEALII_ADAPTER_REF: "02c5d18" # develop, April 12, 2025
DUNE_VERSION: "2.9"
DUMUX_VERSION: "3.7"
-DUMUX_ADAPTER_REF: "0e914bb" # develop, March 18, 2026
-MICRO_MANAGER_REF: "v0.8.0"
+OPENFOAM_EXECUTABLE: "openfoam2512"
+SU2_VERSION: "7.5.1"
+
+# Tested components
+FENICS_ADAPTER_REF: "v2.3.0"
+FENICSX_ADAPTER_REF: "v1.0.1"
+CALCULIX_ADAPTER_REF: "v2.20.1"
+DEALII_ADAPTER_REF: "a421d92" # develop, May 27, 2026
+DUMUX_ADAPTER_REF: "3f3f54f" # develop, May 27, 2026
+MICRO_MANAGER_REF: "v0.10.1"
+OPENFOAM_ADAPTER_REF: "2c3062c" # develop, May 27, 2026
+PRECICE_REF: "v3.4.1"
+PYTHON_BINDINGS_REF: "v3.4.0"
+SU2_ADAPTER_REF: "5abe79b" # develop, May 27, 2026
+TUTORIALS_REF: "develop"
+
+# Additional settings
+PRECICE_PRESET: "production-audit"
\ No newline at end of file
diff --git a/tools/tests/requirements-reference.txt b/tools/tests/requirements-reference.txt
new file mode 100644
index 000000000..9094a61c1
--- /dev/null
+++ b/tools/tests/requirements-reference.txt
@@ -0,0 +1,11 @@
+# Pinned Python dependency versions for reproducible system tests and distributions.
+# Generated from reference_versions.yaml (PYTHON_BINDINGS_REF). Update at each release.
+# Run: python3 update_requirements_reference.py
+#
+# See tools/tests/README.md for how to update this file.
+
+matplotlib==3.9.0
+numpy==1.26.4
+nutils==7.2
+pyprecice==3.2.0
+setuptools>=69.0.0
diff --git a/tools/tests/systemtests.py b/tools/tests/systemtests.py
index 6debe18d0..3183b0ca6 100644
--- a/tools/tests/systemtests.py
+++ b/tools/tests/systemtests.py
@@ -7,9 +7,20 @@
from metadata_parser.metdata import Tutorials, Case
import logging
import time
+import os
+import sys
from paths import PRECICE_TUTORIAL_DIR, PRECICE_TESTS_RUN_DIR, PRECICE_TESTS_DIR
+class _ConsoleLogFormatter(logging.Formatter):
+ """Omit level prefix for INFO/DEBUG; keep it for warnings and errors."""
+
+ def format(self, record: logging.LogRecord) -> str:
+ if record.levelno >= logging.WARNING:
+ return f"{record.levelname}: {record.getMessage()}"
+ return record.getMessage()
+
+
def main():
parser = argparse.ArgumentParser(description='systemtest')
@@ -19,22 +30,40 @@ def main():
parser.add_argument(
'--build_args',
type=str,
- help='Comma-separated list of arguments provided to the components like openfoam:2102,pythonbindings:latest')
+ help='Comma-separated list of component build arguments (e.g., "PRECICE_REF:develop,OPENFOAM_ADAPTER_REF:develop")')
parser.add_argument('--rundir', type=str, help='Directory to run the systemstests in.',
nargs='?', const=PRECICE_TESTS_RUN_DIR, default=PRECICE_TESTS_RUN_DIR)
- parser.add_argument('--log-level', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
- default='INFO', help='Set the logging level')
+ parser.add_argument('--log_level', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
+ default='INFO', help='Set the logging level of the system tests scripts.')
# Parse the command-line arguments
args = parser.parse_args()
- # Configure logging based on the provided log level
- logging.basicConfig(level=args.log_level, format='%(levelname)s: %(message)s')
+ # Configure logging
+ handler = logging.StreamHandler()
+ handler.setFormatter(_ConsoleLogFormatter())
+ logging.basicConfig(level=args.log_level, handlers=[handler])
+
+ gh_actions = os.environ.get("GITHUB_ACTIONS", "").lower() == "true"
+ # Skip ANSI colors when TERM is unset or "dumb" (minimal terminal, common in CI).
+ ansi_colors = sys.stdout.isatty() and os.environ.get("TERM", "") not in {"", "dumb"}
+
+ def _style(text: str, color_code: int | None) -> str:
+ if not ansi_colors or color_code is None:
+ return text
+ return f"\x1b[{color_code}m{text}\x1b[0m"
+
+ def _group_start(title: str) -> None:
+ if gh_actions:
+ print(f"::group::{title}", flush=True)
- print(f"Using log-level: {args.log_level}")
+ def _group_end() -> None:
+ if gh_actions:
+ print("::endgroup::", flush=True)
systemtests_to_run = []
+ test_suites_to_execute = []
available_tutorials = Tutorials.from_path(PRECICE_TUTORIAL_DIR)
build_args = SystemtestArguments.from_args(args.build_args)
@@ -43,7 +72,6 @@ def main():
test_suites_requested = args.suites.split(',')
available_testsuites = TestSuites.from_yaml(
PRECICE_TESTS_DIR / "tests.yaml", available_tutorials)
- test_suites_to_execute = []
for test_suite_requested in test_suites_requested:
test_suite_found = available_testsuites.get_by_name(
test_suite_requested)
@@ -72,24 +100,47 @@ def main():
if not systemtests_to_run:
raise RuntimeError("Did not find any Systemtests to execute.")
- logging.info(f"About to run the following systemtest in the directory {run_directory}:\n {systemtests_to_run}")
+ total = len(systemtests_to_run)
+
+ if test_suites_to_execute:
+ print("Selected test suite(s):", flush=True)
+ print(flush=True)
+ for test_suite in test_suites_to_execute:
+ print(f"- {test_suite.name}", flush=True)
+ print(flush=True)
+
+ print(f"About to run {total} test(s) in the directory {run_directory}:", flush=True)
+ print(flush=True)
+ for number, systemtest in enumerate(systemtests_to_run, start=1):
+ print(f"{number}. {systemtest}", flush=True)
+ print(flush=True)
+ print(f"Using log_level: {args.log_level}", flush=True)
results = []
for number, systemtest in enumerate(systemtests_to_run, start=1):
- logging.info(f"Started running {systemtest}, {number}/{len(systemtests_to_run)}")
- t = time.perf_counter()
- result = systemtest.run(run_directory)
- elapsed_time = time.perf_counter() - t
- logging.info(f"Running {systemtest} took {elapsed_time:^.1f} seconds")
+ print(flush=True)
+ started_header = f"[{number}/{total}] Started {systemtest}"
+ _group_start(started_header)
+ try:
+ if not gh_actions:
+ logging.info(started_header)
+ t = time.perf_counter()
+ result = systemtest.run(run_directory)
+ elapsed_time = time.perf_counter() - t
+
+ if result.success:
+ status_label = _style("✅ PASS", 32)
+ else:
+ status_label = _style("❌ FAIL", 31)
+ finally:
+ _group_end()
+
+ print(f"{status_label} Finished in {elapsed_time:.1f}s", flush=True)
+ print(flush=True)
results.append(result)
- system_test_success = True
- for result in results:
- if not result.success:
- logging.error(f"Failed to run {result.systemtest}")
- system_test_success = False
- else:
- logging.info(f"Success running {result.systemtest}")
+ print(flush=True)
+ system_test_success = all(result.success for result in results)
display_systemtestresults_as_table(results)
if system_test_success:
diff --git a/tools/tests/systemtests/Systemtest.py b/tools/tests/systemtests/Systemtest.py
index 19d48ae7f..932b6b944 100644
--- a/tools/tests/systemtests/Systemtest.py
+++ b/tools/tests/systemtests/Systemtest.py
@@ -1,4 +1,5 @@
import subprocess
+import threading
from typing import List, Dict, Optional, Tuple
from jinja2 import Environment, FileSystemLoader
from dataclasses import dataclass, field
@@ -19,11 +20,43 @@
import os
-GLOBAL_TIMEOUT = int(os.environ.get("PRECICE_SYSTEMTESTS_TIMEOUT", 900))
+GLOBAL_TIMEOUT = int(os.environ.get("PRECICE_SYSTEMTESTS_TIMEOUT", 600))
SHORT_TIMEOUT = 10
DIFF_RESULTS_DIR = "diff-results"
+STAGE_LOG_FILES = {
+ "build": "system-tests-build.log",
+ "run": "system-tests-run.log",
+ "compare": "system-tests-compare.log",
+}
+
+FAILURE_LOG_TAIL_LINES = 100
+
+
+class _SystemtestLogSink:
+ """Writes subprocess output incrementally to per-stage log files."""
+
+ def __init__(self, system_test_dir: Path):
+ self._system_test_dir = system_test_dir
+ self._lock = threading.Lock()
+
+ def begin_stage(self, stage: str) -> None:
+ stage_path = self._system_test_dir / STAGE_LOG_FILES[stage]
+ stage_path.write_text(f"=== {stage} ===\n", encoding="utf-8")
+
+ def append_stdout(self, line: str, stage: str) -> None:
+ with self._lock:
+ stage_path = self._system_test_dir / STAGE_LOG_FILES[stage]
+ with stage_path.open("a", encoding="utf-8") as log_file:
+ log_file.write(line + "\n")
+
+ def append_stderr(self, line: str, stage: str) -> None:
+ with self._lock:
+ stage_path = self._system_test_dir / STAGE_LOG_FILES[stage]
+ with stage_path.open("a", encoding="utf-8") as log_file:
+ log_file.write(f"[stderr] {line}\n")
+
def slugify(value, allow_unicode=False):
"""
@@ -76,17 +109,62 @@ class SystemtestResult:
fieldcompare_time: float # in seconds
+def _success_status_symbol(success: bool) -> str:
+ return "✅" if success else "❌"
+
+
+def _read_log_tail(log_path: Path, max_lines: int = FAILURE_LOG_TAIL_LINES) -> str:
+ lines = log_path.read_text(encoding="utf-8", errors="replace").splitlines()
+ if not lines:
+ return "(log file is empty)"
+ return "\n".join(lines[-max_lines:])
+
+
+def _append_failure_log_tails_to_summary(results: List[SystemtestResult]) -> None:
+ summary_path = os.environ.get("GITHUB_STEP_SUMMARY")
+ if not summary_path:
+ return
+
+ failed_results = [result for result in results if not result.success]
+ if not failed_results:
+ return
+
+ with open(summary_path, "a", encoding="utf-8") as summary_file:
+ print("\n## Failed test logs\n", file=summary_file)
+ for result in failed_results:
+ print(
+ f"### {_success_status_symbol(False)} {result.systemtest}\n",
+ file=summary_file,
+ )
+ run_dir = result.systemtest.get_system_test_dir()
+ for log_name in STAGE_LOG_FILES.values():
+ log_path = run_dir / log_name
+ if not log_path.is_file():
+ continue
+ tail = _read_log_tail(log_path)
+ print("", file=summary_file)
+ print(f"{log_name} tail
", file=summary_file)
+ print("", file=summary_file)
+ print("```text", file=summary_file)
+ print(tail, file=summary_file)
+ print("```", file=summary_file)
+ print(" ", file=summary_file)
+ print("", file=summary_file)
+
+
def display_systemtestresults_as_table(results: List[SystemtestResult]):
"""
Prints the result in a nice tabluated way to get an easy overview
"""
+ print()
+
def _get_length_of_name(results: List[SystemtestResult]) -> int:
return max(len(str(result.systemtest)) for result in results)
max_name_length = _get_length_of_name(results)
header = f"| {'systemtest':<{max_name_length + 2}} "\
- f"| {'success':^7} "\
+ f"| {'status':^7} "\
f"| {'building time [s]':^17} "\
f"| {'solver time [s]':^15} "\
f"| {'fieldcompare time [s]':^21} |"
@@ -105,7 +183,7 @@ def _get_length_of_name(results: List[SystemtestResult]) -> int:
for result in results:
row = f"| {str(result.systemtest):<{max_name_length + 2}} "\
- f"| {result.success:^7} "\
+ f"| {_success_status_symbol(result.success):^7} "\
f"| {result.build_time:^17.1f} "\
f"| {result.solver_time:^15.1f} "\
f"| {result.fieldcompare_time:^21.1f} |"
@@ -115,11 +193,13 @@ def _get_length_of_name(results: List[SystemtestResult]) -> int:
with open(os.environ["GITHUB_STEP_SUMMARY"], "a") as f:
print(row, file=f)
+ _append_failure_log_tails_to_summary(results)
+
if "GITHUB_STEP_SUMMARY" in os.environ:
with open(os.environ["GITHUB_STEP_SUMMARY"], "a") as f:
print("\n\n", file=f)
print(
- "In case a test fails, download the archive from the bottom of this page and look into each `system-tests-stdout.log` and `system-tests-stderr.log`. The time spent in each step might already give useful hints.",
+ "In case a test fails, download the archive from the bottom of this page and inspect the per-stage logs (`system-tests-build.log`, `system-tests-run.log`, `system-tests-compare.log`). The stage runtimes might already give useful hints.",
file=f)
print(
"See the [documentation](https://precice.org/dev-docs-system-tests.html#understanding-what-went-wrong).",
@@ -176,9 +256,21 @@ def __init_args_to_use(self):
# Substitute defaults for non-provided, needed arguments
for needed_param in needed_parameters:
if not needed_param.key in provided_arguments:
- logging.warning(
- f"No argument provided for needed parameter {needed_param.key}. Substituting with {needed_param.default}")
+ logging.info(
+ f"No argument provided for needed parameter {needed_param.key}. Substituting with {needed_param.default}.")
self.params_to_use[needed_param.key] = needed_param.default
+ if needed_param.key.endswith("_REF") and needed_param.key in provided_arguments:
+ logging.debug(
+ f"The parameter {needed_param.key} points to the repository {needed_param.repository}.")
+ # If a commit has already been resolved and added to the params_to_use, it will be propagated to the next test in the test suite.
+ # To avoid resolving the same commit again, simply check if the key has the same length as the output of _resolve_branch_ref_to_commit.
+ # The whole process assumes that all components use the same refs.
+ if len(self.params_to_use[needed_param.key]) == 40:
+ logging.debug(
+ f"Git ref {self.params_to_use[needed_param.key]} is 40 characters long and probably already a commit.")
+ else:
+ self.params_to_use[needed_param.key] = self._resolve_branch_ref_to_commit(
+ needed_param.repository, self.params_to_use[needed_param.key])
def __get_docker_services(self) -> Dict[str, str]:
"""
@@ -282,7 +374,32 @@ def _fetch_ref(self, repository: Path, ref: str):
raise RuntimeError(f"git command returned code {result.returncode}")
except Exception as e:
- raise RuntimeError(f"An error occurred while fetching origin '{ref}': {e}")
+ raise RuntimeError(
+ f"An error occurred while fetching origin '{ref}': {e}. Do the values in reference_versions.yaml point to (still) valid Git refs?")
+
+ def _resolve_branch_ref_to_commit(self, repository: Path, ref: str) -> Optional[str]:
+ try:
+ git_ls_remote_output = subprocess.run([
+ "git",
+ "ls-remote",
+ os.fspath(repository),
+ ref,
+ ], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=True, timeout=60)
+
+ # If an invalid ref is given, git ls-remote still returns success, but no list
+ git_remote_refs = git_ls_remote_output.stdout.strip()
+ if not git_remote_refs:
+ raise ValueError(f"The git ref {ref} does not appear in the repository {repository}.")
+
+ commit = git_remote_refs.split()[0]
+ # The output assumes a URL of the form /commits/. Works for GitHub and Bitbucket.
+ logging.info(
+ f"Resolved the git ref {ref} of the repository {repository} to {repository}/commits/{commit} .")
+ return commit if commit else ref
+ except Exception:
+ logging.warning(
+ f"Could not resolve git ref {ref} of the repository {repository} to a commit. Using the given git ref as-is.")
+ return ref
def _checkout_ref_in_subfolder(self, repository: Path, subfolder: Path, ref: str):
try:
@@ -398,58 +515,159 @@ def __unpack_reference_results(self) -> Tuple[bool, str]:
logging.error(error_message)
return False, error_message
- def _run_field_compare(self):
+ def __init_run_logs(self) -> None:
+ self._log_sink = _SystemtestLogSink(self.system_test_dir)
+
+ def _run_docker_compose_subprocess(
+ self,
+ command: List[str],
+ stage: str,
+ timeout: int,
+ ) -> Tuple[int, List[str], List[str]]:
"""
- Executes the field comparison step after unpacking reference results.
+ Run a docker compose command, streaming stdout/stderr to log files as they arrive.
+ """
+ stdout_data: List[str] = []
+ stderr_data: List[str] = []
+ log_sink = getattr(self, "_log_sink", None)
+ if log_sink is not None:
+ log_sink.begin_stage(stage)
+ logging.info(f"Docker compose {stage} for {self}")
- Returns:
- A FieldCompareResult object containing the command outcome and logs.
+ try:
+ process = subprocess.Popen(
+ command,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ text=True,
+ bufsize=1,
+ start_new_session=True,
+ cwd=self.system_test_dir,
+ )
+ except Exception as e:
+ logging.critical(f"Error starting docker compose {stage} command: {e}")
+ return 1, stdout_data, stderr_data
+
+ def read_stream(stream, is_stderr: bool) -> None:
+ if stream is None:
+ return
+ for line in stream:
+ line = line.rstrip("\n\r")
+ if is_stderr:
+ stderr_data.append(line)
+ if log_sink is not None:
+ log_sink.append_stderr(line, stage)
+ else:
+ stdout_data.append(line)
+ if log_sink is not None:
+ log_sink.append_stdout(line, stage)
+ stream.close()
+
+ stdout_thread = threading.Thread(
+ target=read_stream, args=(process.stdout, False), daemon=True)
+ stderr_thread = threading.Thread(
+ target=read_stream, args=(process.stderr, True), daemon=True)
+ stdout_thread.start()
+ stderr_thread.start()
+
+ try:
+ exit_code = process.wait(timeout=timeout)
+ except KeyboardInterrupt as k:
+ process.kill()
+ stdout_thread.join(timeout=SHORT_TIMEOUT)
+ stderr_thread.join(timeout=SHORT_TIMEOUT)
+ raise KeyboardInterrupt from k
+ except subprocess.TimeoutExpired:
+ logging.critical(
+ f"Systemtest {self} timed out during docker compose {stage} "
+ f"after {timeout}s. Killing the process.")
+ process.kill()
+ try:
+ process.wait(timeout=SHORT_TIMEOUT)
+ except subprocess.TimeoutExpired:
+ pass
+ exit_code = process.returncode if process.returncode is not None else 1
+ except Exception as e:
+ logging.critical(
+ f"Systemtest {self} had serious issues during docker compose {stage}: {e}")
+ process.kill()
+ try:
+ process.wait(timeout=SHORT_TIMEOUT)
+ except subprocess.TimeoutExpired:
+ pass
+ exit_code = process.returncode if process.returncode is not None else 1
+
+ stdout_thread.join(timeout=SHORT_TIMEOUT)
+ stderr_thread.join(timeout=SHORT_TIMEOUT)
+ if exit_code is None:
+ exit_code = process.poll() or 1
+ return exit_code, stdout_data, stderr_data
+
+ def _cleanup_docker_networks(self):
"""
- logging.debug(f"Running fieldcompare for {self}")
- time_start = time.perf_counter()
- unpack_success, unpack_error_message = self.__unpack_reference_results()
- if not unpack_success:
- elapsed_time = time.perf_counter() - time_start
- return FieldCompareResult(1, [], [unpack_error_message], self, elapsed_time)
- docker_compose_content = self.__get_field_compare_compose_file()
+ Prunes the unused Docker networks, since there is an upper limit on the number of custom networks defined.
+ """
+ logging.debug(f"Deleting unused Docker networks...")
stdout_data = []
stderr_data = []
-
- with open(self.system_test_dir / "docker-compose.field_compare.yaml", 'w') as file:
- file.write(docker_compose_content)
try:
- # Execute docker-compose command
+ # Execute docker-network-prune command
process = subprocess.Popen(['docker',
- 'compose',
- '--file',
- 'docker-compose.field_compare.yaml',
- 'up',
- '--exit-code-from',
- 'field-compare'],
+ 'network',
+ 'prune',
+ '-f'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
start_new_session=True,
cwd=self.system_test_dir)
-
try:
stdout, stderr = process.communicate(timeout=self.timeout)
except KeyboardInterrupt as k:
process.kill()
raise KeyboardInterrupt from k
- except Exception as e:
- logging.critical(
- f"Systemtest {self} had serious issues executing the docker compose command about to kill the docker compose command. Please check the logs! {e}")
- process.kill()
- process.communicate(timeout=SHORT_TIMEOUT)
+ except Exception as e:
+ logging.critical(
+ f"Systemtest {self} could not prune the Docker networks. This might prevent tests from starting.")
stdout_data.extend(stdout.decode().splitlines())
stderr_data.extend(stderr.decode().splitlines())
process.poll()
+
+ def _run_field_compare(self):
+ """
+ Executes the field comparison step after unpacking reference results.
+
+ Returns:
+ A FieldCompareResult object containing the command outcome and logs.
+ """
+ logging.debug(f"Running fieldcompare for {self}")
+ time_start = time.perf_counter()
+ unpack_success, unpack_error_message = self.__unpack_reference_results()
+ if not unpack_success:
+ log_sink = getattr(self, "_log_sink", None)
+ if log_sink is not None:
+ log_sink.begin_stage("compare")
+ log_sink.append_stderr(unpack_error_message, "compare")
elapsed_time = time.perf_counter() - time_start
- return FieldCompareResult(process.returncode, stdout_data, stderr_data, self, elapsed_time)
- except Exception as e:
- logging.CRITICAL("Error executing docker compose command:", e)
- elapsed_time = time.perf_counter() - time_start
- return FieldCompareResult(1, stdout_data, stderr_data, self, elapsed_time)
+ return FieldCompareResult(1, [], [unpack_error_message], self, elapsed_time)
+ docker_compose_content = self.__get_field_compare_compose_file()
+
+ with open(self.system_test_dir / "docker-compose.field_compare.yaml", 'w') as file:
+ file.write(docker_compose_content)
+ exit_code, stdout_data, stderr_data = self._run_docker_compose_subprocess(
+ [
+ 'docker',
+ 'compose',
+ '--file',
+ 'docker-compose.field_compare.yaml',
+ 'up',
+ '--exit-code-from',
+ 'field-compare',
+ ],
+ "compare",
+ self.timeout,
+ )
+ elapsed_time = time.perf_counter() - time_start
+ return FieldCompareResult(exit_code, stdout_data, stderr_data, self, elapsed_time)
def __archive_fieldcompare_diffs(self) -> None:
"""
@@ -501,41 +719,20 @@ def _build_docker(self):
with open(self.system_test_dir / "docker-compose.tutorial.yaml", 'w') as file:
file.write(docker_compose_content)
- stdout_data = []
- stderr_data = []
-
- try:
- # Execute docker-compose command
- process = subprocess.Popen(['docker',
- 'compose',
- '--file',
- 'docker-compose.tutorial.yaml',
- 'build'],
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- start_new_session=True,
- cwd=self.system_test_dir)
-
- try:
- stdout, stderr = process.communicate(timeout=GLOBAL_TIMEOUT)
- except KeyboardInterrupt as k:
- process.kill()
- # process.send_signal(9)
- raise KeyboardInterrupt from k
- except Exception as e:
- logging.critical(
- f"systemtest {self} had serious issues building the docker images via the `docker compose build` command. About to kill the docker compose command. Please check the logs! {e}")
- process.communicate(timeout=SHORT_TIMEOUT)
- process.kill()
-
- stdout_data.extend(stdout.decode().splitlines())
- stderr_data.extend(stderr.decode().splitlines())
- elapsed_time = time.perf_counter() - time_start
- return DockerComposeResult(process.returncode, stdout_data, stderr_data, self, elapsed_time)
- except Exception as e:
- logging.critical(f"Error executing docker compose build command: {e}")
- elapsed_time = time.perf_counter() - time_start
- return DockerComposeResult(1, stdout_data, stderr_data, self, elapsed_time)
+ exit_code, stdout_data, stderr_data = self._run_docker_compose_subprocess(
+ [
+ 'docker',
+ 'compose',
+ '--progress=plain',
+ '--file',
+ 'docker-compose.tutorial.yaml',
+ 'build',
+ ],
+ "build",
+ GLOBAL_TIMEOUT,
+ )
+ elapsed_time = time.perf_counter() - time_start
+ return DockerComposeResult(exit_code, stdout_data, stderr_data, self, elapsed_time)
def _run_tutorial(self):
"""
@@ -546,51 +743,23 @@ def _run_tutorial(self):
"""
logging.debug(f"Running tutorial {self}")
time_start = time.perf_counter()
- stdout_data = []
- stderr_data = []
- try:
- # Execute docker-compose command
- process = subprocess.Popen(['docker',
- 'compose',
- '--file',
- 'docker-compose.tutorial.yaml',
- 'up'],
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- start_new_session=True,
- cwd=self.system_test_dir)
-
- try:
- stdout, stderr = process.communicate(timeout=self.timeout)
- except KeyboardInterrupt as k:
- process.kill()
- # process.send_signal(9)
- raise KeyboardInterrupt from k
- except Exception as e:
- logging.critical(
- f"Systemtest {self} had serious issues executing the docker compose command about to kill the docker compose command. Please check the logs! {e}")
- process.kill()
- stdout, stderr = process.communicate(timeout=SHORT_TIMEOUT)
- process.kill()
-
- stdout_data.extend(stdout.decode().splitlines())
- stderr_data.extend(stderr.decode().splitlines())
- elapsed_time = time.perf_counter() - time_start
- return DockerComposeResult(process.returncode, stdout_data, stderr_data, self, elapsed_time)
- except Exception as e:
- logging.critical(f"Error executing docker compose up command: {e}")
- elapsed_time = time.perf_counter() - time_start
- return DockerComposeResult(1, stdout_data, stderr_data, self, elapsed_time)
+ exit_code, stdout_data, stderr_data = self._run_docker_compose_subprocess(
+ [
+ 'docker',
+ 'compose',
+ '--file',
+ 'docker-compose.tutorial.yaml',
+ 'up',
+ ],
+ "run",
+ self.timeout,
+ )
+ elapsed_time = time.perf_counter() - time_start
+ return DockerComposeResult(exit_code, stdout_data, stderr_data, self, elapsed_time)
def __repr__(self):
return f"{self.tutorial.name} {self.case_combination}"
- def __write_logs(self, stdout_data: List[str], stderr_data: List[str]):
- with open(self.system_test_dir / "system-tests-stdout.log", 'w') as stdout_file:
- stdout_file.write("\n".join(stdout_data))
- with open(self.system_test_dir / "system-tests-stderr.log", 'w') as stderr_file:
- stderr_file.write("\n".join(stderr_data))
-
def __apply_max_time_override(self):
"""Overwrite or value in precice-config.xml."""
if self.max_time is None and self.max_time_windows is None:
@@ -631,14 +800,15 @@ def run(self, run_directory: Path):
Runs the system test by generating the Docker Compose file, copying everything into a run folder, and executing docker-compose up.
"""
self.__prepare_for_run(run_directory)
+ self.__init_run_logs()
std_out: List[str] = []
std_err: List[str] = []
+ self._cleanup_docker_networks()
docker_build_result = self._build_docker()
std_out.extend(docker_build_result.stdout_data)
std_err.extend(docker_build_result.stderr_data)
if docker_build_result.exit_code != 0:
- self.__write_logs(std_out, std_err)
logging.critical(f"Could not build the docker images, {self} failed")
return SystemtestResult(
False,
@@ -653,7 +823,6 @@ def run(self, run_directory: Path):
std_out.extend(docker_run_result.stdout_data)
std_err.extend(docker_run_result.stderr_data)
if docker_run_result.exit_code != 0:
- self.__write_logs(std_out, std_err)
logging.critical(f"Could not run the tutorial, {self} failed")
return SystemtestResult(
False,
@@ -669,7 +838,6 @@ def run(self, run_directory: Path):
std_err.extend(fieldcompare_result.stderr_data)
if fieldcompare_result.exit_code != 0:
self.__archive_fieldcompare_diffs()
- self.__write_logs(std_out, std_err)
logging.critical(f"Fieldcompare returned non zero exit code, therefore {self} failed")
return SystemtestResult(
False,
@@ -681,7 +849,7 @@ def run(self, run_directory: Path):
fieldcompare_time=fieldcompare_result.runtime)
# self.__cleanup()
- self.__write_logs(std_out, std_err)
+ self._cleanup_docker_networks()
return SystemtestResult(
True,
std_out,
@@ -696,13 +864,14 @@ def run_for_reference_results(self, run_directory: Path):
Runs the system test by generating the Docker Compose files to generate the reference results
"""
self.__prepare_for_run(run_directory)
+ self.__init_run_logs()
std_out: List[str] = []
std_err: List[str] = []
+ self._cleanup_docker_networks()
docker_build_result = self._build_docker()
std_out.extend(docker_build_result.stdout_data)
std_err.extend(docker_build_result.stderr_data)
if docker_build_result.exit_code != 0:
- self.__write_logs(std_out, std_err)
logging.critical(f"Could not build the docker images, {self} failed")
return SystemtestResult(
False,
@@ -717,7 +886,6 @@ def run_for_reference_results(self, run_directory: Path):
std_out.extend(docker_run_result.stdout_data)
std_err.extend(docker_run_result.stderr_data)
if docker_run_result.exit_code != 0:
- self.__write_logs(std_out, std_err)
logging.critical(f"Could not run the tutorial, {self} failed")
return SystemtestResult(
False,
@@ -728,7 +896,7 @@ def run_for_reference_results(self, run_directory: Path):
solver_time=docker_run_result.runtime,
fieldcompare_time=0)
- self.__write_logs(std_out, std_err)
+ self._cleanup_docker_networks()
return SystemtestResult(
True,
std_out,
@@ -743,13 +911,13 @@ def run_only_build(self, run_directory: Path):
Runs only the build commmand, for example to preheat the caches of the docker builder.
"""
self.__prepare_for_run(run_directory)
+ self.__init_run_logs()
std_out: List[str] = []
std_err: List[str] = []
docker_build_result = self._build_docker()
std_out.extend(docker_build_result.stdout_data)
std_err.extend(docker_build_result.stderr_data)
if docker_build_result.exit_code != 0:
- self.__write_logs(std_out, std_err)
logging.critical(f"Could not build the docker images, {self} failed")
return SystemtestResult(
False,
@@ -760,7 +928,6 @@ def run_only_build(self, run_directory: Path):
solver_time=0,
fieldcompare_time=0)
- self.__write_logs(std_out, std_err)
return SystemtestResult(
True,
std_out,
diff --git a/tools/tests/systemtests/SystemtestArguments.py b/tools/tests/systemtests/SystemtestArguments.py
index 2b7b3eeec..4425472bc 100644
--- a/tools/tests/systemtests/SystemtestArguments.py
+++ b/tools/tests/systemtests/SystemtestArguments.py
@@ -16,7 +16,8 @@ def from_args(cls, cmd_args):
arguments = {}
for param in params_provided:
key, value = param.split(":")
- arguments[key] = value
+ if len(value) > 0:
+ arguments[key] = value
return cls(arguments)
diff --git a/tools/tests/systemtests/TestSuite.py b/tools/tests/systemtests/TestSuite.py
index dff317ad9..a498ca4bd 100644
--- a/tools/tests/systemtests/TestSuite.py
+++ b/tools/tests/systemtests/TestSuite.py
@@ -93,7 +93,7 @@ def from_yaml(cls, path, parsed_tutorials: Tutorials):
timeouts_of_tutorial[tutorial].append(timeout_value)
else:
raise Exception(
- f"Could not find the following cases {tutorial_case['case-combination']} in the current metadata of tutorial {tutorial.name}")
+ f"Could not find the case combination {tutorial_case['case_combination']} in the current metadata of tutorial {tutorial.name}, or it does not define all necessary participants.")
testsuites.append(TestSuite(test_suite_name, case_combinations_of_tutorial,
reference_results_of_tutorial, max_times_of_tutorial, max_time_windows_of_tutorial, timeouts_of_tutorial))
diff --git a/tools/tests/tests.yaml b/tools/tests/tests.yaml
index 1cac21867..70faade1d 100644
--- a/tools/tests/tests.yaml
+++ b/tools/tests/tests.yaml
@@ -1,205 +1,748 @@
+# Test suites that can be triggered by the system tests.
+# Define test suites per tutorial in the beginning of the file,
+# then refer to these in the release test suite and in the individual test
+# suites for repositories, at the lower part of the file.
+#
+# Conventions:
+# - Test suites follow the name of the respective tutorial or repository
+# - Tests suites append the entries of the case_combination, separated by underscore
+# - Test suites and tests are sorted alphabetically
+# - Every test suite for a component includes by default all test cases that use that component.
+# Skipped components are still mentioned in a comment.
+
test_suites:
- quickstart_test:
+ breaking-dam-2d:
tutorials:
- - &quickstart
- path: quickstart
+ - &breaking-dam-2d_fluid-openfoam_solid-calculix
+ path: breaking-dam-2d
case_combination:
- fluid-openfoam
- - solid-cpp
- reference_result: ./quickstart/reference-results/fluid-openfoam_solid-cpp.tar.gz
- openfoam_adapter_pr:
+ - solid-calculix
+ max_time: 0.2
+ reference_result: ./breaking-dam-2d/reference-results/fluid-openfoam_solid-calculix.tar.gz
+
+ channel-transport:
tutorials:
- - *quickstart
- - path: flow-over-heated-plate
+ - &channel-transport_fluid-nutils_transport-nutils
+ path: channel-transport
+ case_combination:
+ - fluid-nutils
+ - transport-nutils
+ max_time: 0.05
+ reference_result: ./channel-transport/reference-results/fluid-nutils_transport-nutils.tar.gz
+ - &channel-transport_fluid-openfoam_transport-nutils
+ path: channel-transport
case_combination:
- fluid-openfoam
- - solid-openfoam
- reference_result: ./flow-over-heated-plate/reference-results/fluid-openfoam_solid-openfoam.tar.gz
- - path: perpendicular-flap
+ - transport-nutils
+ max_time: 0.1
+ reference_result: ./channel-transport/reference-results/fluid-openfoam_transport-nutils.tar.gz
+
+ channel-transport-reaction:
+ tutorials:
+ - &channel-transport-reaction_fluid-fenics_chemical-fenics
+ path: channel-transport-reaction
+ case_combination:
+ - fluid-fenics
+ - chemical-fenics
+ max_time: 0.5
+ reference_result: ./channel-transport-reaction/reference-results/fluid-fenics_chemical-fenics.tar.gz
+
+ channel-transport-particles:
+ tutorials:
+ - &channel-transport-particles_fluid-openfoam_particles-mercurydpm
+ path: channel-transport-particles
case_combination:
- fluid-openfoam
- - solid-calculix
- reference_result: ./perpendicular-flap/reference-results/fluid-openfoam_solid-calculix.tar.gz
- - path: perpendicular-flap
+ - particles-mercurydpm
+ max_time: 0.025
+ reference_result: ./channel-transport-particles/reference-results/fluid-openfoam_particles-mercurydpm.tar.gz
+ - &channel-transport-particles_fluid-nutils_particles-mercurydpm
+ path: channel-transport-particles
+ case_combination:
+ - fluid-nutils
+ - particles-mercurydpm
+ max_time: 0.025
+ reference_result: ./channel-transport-particles/reference-results/fluid-nutils_particles-mercurydpm.tar.gz
+
+ elastic-tube-1d:
+ tutorials:
+ - &elastic-tube-1d_fluid-cpp_solid-cpp
+ path: elastic-tube-1d
+ case_combination:
+ - fluid-cpp
+ - solid-cpp
+ reference_result: ./elastic-tube-1d/reference-results/fluid-cpp_solid-cpp.tar.gz
+ - &elastic-tube-1d_fluid-cpp_solid-python
+ path: elastic-tube-1d
+ case_combination:
+ - fluid-cpp
+ - solid-python
+ max_time: 0.1
+ reference_result: ./elastic-tube-1d/reference-results/fluid-cpp_solid-python.tar.gz
+ - &elastic-tube-1d_fluid-fortran_solid-fortran
+ path: elastic-tube-1d
+ case_combination:
+ - fluid-fortran
+ - solid-fortran
+ reference_result: ./elastic-tube-1d/reference-results/fluid-fortran_solid-fortran.tar.gz
+ - &elastic-tube-1d_fluid-fortran-module_solid-fortran-module
+ path: elastic-tube-1d
+ case_combination:
+ - fluid-fortran-module
+ - solid-fortran-module
+ reference_result: ./elastic-tube-1d/reference-results/fluid-fortran-module_solid-fortran-module.tar.gz
+ - &elastic-tube-1d_fluid-python_solid-python
+ path: elastic-tube-1d
+ case_combination:
+ - fluid-python
+ - solid-python
+ reference_result: ./elastic-tube-1d/reference-results/fluid-python_solid-python.tar.gz
+
+ elastic-tube-3d:
+ tutorials:
+ - &elastic-tube-3d_fluid-openfoam_solid-calculix
+ path: elastic-tube-3d
case_combination:
- fluid-openfoam
- - solid-openfoam
- reference_result: ./perpendicular-flap/reference-results/fluid-openfoam_solid-openfoam.tar.gz
- - path: flow-over-heated-plate-nearest-projection
+ - solid-calculix
+ max_time_windows: 3
+ reference_result: ./elastic-tube-3d/reference-results/fluid-openfoam_solid-calculix.tar.gz
+ - &elastic-tube-3d_fluid-openfoam_solid-fenics
+ path: elastic-tube-3d
case_combination:
- fluid-openfoam
- - solid-openfoam
- reference_result: ./flow-over-heated-plate-nearest-projection/reference-results/fluid-openfoam_solid-openfoam.tar.gz
- openfoam_adapter_release:
+ - solid-fenics
+ max_time_windows: 1
+ reference_result: ./elastic-tube-3d/reference-results/fluid-openfoam_solid-fenics.tar.gz # Too small values, expected to fail the comparisons.
+
+ flow-around-controlled-moving-cylinder:
tutorials:
- - path: flow-over-heated-plate
+ - &flow-around-controlled-moving-cylinder_controller-fmi_fluid-openfoam_solid-python
+ path: flow-around-controlled-moving-cylinder
case_combination:
+ - controller-fmi
- fluid-openfoam
- - solid-openfoam
- reference_result: ./flow-over-heated-plate/reference-results/fluid-openfoam_solid-openfoam.tar.gz
- fenics_test:
+ - solid-python
+ max_time: 0.01
+ reference_result: ./flow-around-controlled-moving-cylinder/reference-results/controller-fmi_fluid-openfoam_solid-python.tar.gz
+
+ flow-over-heated-plate:
tutorials:
- - path: flow-over-heated-plate
+ - &flow-over-heated-plate_fluid-openfoam_solid-fenics
+ path: flow-over-heated-plate
case_combination:
- fluid-openfoam
- solid-fenics
reference_result: ./flow-over-heated-plate/reference-results/fluid-openfoam_solid-fenics.tar.gz
- - path: perpendicular-flap
+ - &flow-over-heated-plate_fluid-openfoam_solid-fenicsx
+ path: flow-over-heated-plate
case_combination:
- - fluid-openfoam
- - solid-fenics
- reference_result: ./perpendicular-flap/reference-results/fluid-openfoam_solid-fenics.tar.gz
- nutils_test:
- tutorials:
- - path: flow-over-heated-plate
+ - fluid-openfoam
+ - solid-fenicsx
+ reference_result: ./flow-over-heated-plate/reference-results/fluid-openfoam_solid-fenicsx.tar.gz
+ - &flow-over-heated-plate_fluid-openfoam_solid-nutils
+ path: flow-over-heated-plate
case_combination:
- fluid-openfoam
- solid-nutils
+ max_time: 0.05
reference_result: ./flow-over-heated-plate/reference-results/fluid-openfoam_solid-nutils.tar.gz
- calculix_test:
+ - &flow-over-heated-plate_fluid-openfoam_solid-openfoam
+ path: flow-over-heated-plate
+ case_combination:
+ - fluid-openfoam
+ - solid-openfoam
+ reference_result: ./flow-over-heated-plate/reference-results/fluid-openfoam_solid-openfoam.tar.gz
+ - &flow-over-heated-plate_fluid-su2_solid-openfoam
+ path: flow-over-heated-plate
+ case_combination:
+ - fluid-su2
+ - solid-openfoam
+ max_time: 0.1
+ reference_result: ./flow-over-heated-plate/reference-results/fluid-su2_solid-openfoam.tar.gz
+
+ flow-over-heated-plate-nearest-projection:
tutorials:
- - path: perpendicular-flap
+ - &flow-over-heated-plate-nearest-projection_fluid-openfoam_solid-openfoam
+ path: flow-over-heated-plate-nearest-projection
case_combination:
- fluid-openfoam
- - solid-calculix
- reference_result: ./perpendicular-flap/reference-results/fluid-openfoam_solid-calculix.tar.gz
- dumux_test:
+ - solid-openfoam
+ max_time: 0.1
+ reference_result: ./flow-over-heated-plate-nearest-projection/reference-results/fluid-openfoam_solid-openfoam.tar.gz
+
+ flow-over-heated-plate-partitioned-flow:
tutorials:
- - path: two-scale-heat-conduction
+ - &flow-over-heated-plate-partitioned-flow_fluid1-openfoam_fluid2-openfoam_solid-openfoam
+ path: flow-over-heated-plate-partitioned-flow
case_combination:
- - macro-dumux
- - micro-dumux
- reference_result: ./two-scale-heat-conduction/reference-results/macro-dumux_micro-dumux.tar.gz # Too small values, expected to fail the comparisons.
- - path: free-flow-over-porous-media
+ - fluid1-openfoam
+ - fluid2-openfoam
+ - solid-openfoam
+ max_time: 0.1
+ reference_result: ./flow-over-heated-plate-partitioned-flow/reference-results/fluid1-openfoam_fluid2-openfoam_solid-openfoam.tar.gz
+
+ flow-over-heated-plate-two-meshes:
+ tutorials:
+ - &flow-over-heated-plate-two-meshes_fluid-openfoam_solid-calculix
+ path: flow-over-heated-plate-two-meshes
+ case_combination:
+ - fluid-openfoam
+ - solid-calculix
+ max_time: 0.1
+ reference_result: ./flow-over-heated-plate-two-meshes/reference-results/fluid-openfoam_solid-openfoam.tar.gz
+
+ free-flow-over-porous-media:
+ tutorials:
+ - &free-flow-over-porous-media_free-flow-dumux_porous-media-dumux
+ path: free-flow-over-porous-media
case_combination:
- free-flow-dumux
- porous-media-dumux
reference_result: ./free-flow-over-porous-media/reference-results/free-flow-dumux_porous-media-dumux.tar.gz
- micro_manager_test:
+
+ heat-exchanger:
tutorials:
- - path: two-scale-heat-conduction
+ - &heat-exchanger_fluid-inner-openfoam_solid-calculix_fluid-outer-openfoam
+ path: heat-exchanger
case_combination:
- - macro-dumux
- - micro-dumux
- reference_result: ./two-scale-heat-conduction/reference-results/macro-dumux_micro-dumux.tar.gz # Too small values, expected to fail the comparisons.
- su2_test:
- tutorials:
- - path: perpendicular-flap
- case_combination:
- - fluid-su2
- - solid-fenics
- reference_result: ./perpendicular-flap/reference-results/fluid-su2_solid-fenics.tar.gz
- heat_exchanger_simplified_test:
+ - fluid-inner-openfoam
+ - fluid-outer-openfoam
+ - solid-calculix
+ max_time: 3
+ reference_result: ./heat-exchanger/reference-results/fluid-inner-openfoam_solid-calculix_fluid-outer-openfoam.tar.gz
+
+ heat-exchanger-simplified:
tutorials:
- - &heat_exchanger_simplified
+ - &heat-exchanger-simplified_fluid-top-openfoam_fluid-bottom-openfoam_solid-calculix
path: heat-exchanger-simplified
case_combination:
- fluid-top-openfoam
- fluid-bottom-openfoam
- solid-calculix
+ max_time: 0.05
reference_result: ./heat-exchanger-simplified/reference-results/fluid-top-openfoam_fluid-bottom-openfoam_solid-calculix.tar.gz
- dealii_test:
+
+ multiple-perpendicular-flaps:
tutorials:
- - path: perpendicular-flap
- case_combination:
- - fluid-openfoam
- - solid-dealii
- reference_result: ./perpendicular-flap/reference-results/fluid-openfoam_solid-dealii.tar.gz
- - path: perpendicular-flap
- case_combination:
- - fluid-openfoam
- - solid-openfoam
- reference_result: ./perpendicular-flap/reference-results/fluid-openfoam_solid-openfoam.tar.gz
- - path: perpendicular-flap
- case_combination:
- - fluid-openfoam
- - solid-fenics
- reference_result: ./perpendicular-flap/reference-results/fluid-openfoam_solid-fenics.tar.gz
- - path: flow-over-heated-plate-nearest-projection
- case_combination:
- - fluid-openfoam
- - solid-openfoam
- reference_result: ./flow-over-heated-plate-nearest-projection/reference-results/fluid-openfoam_solid-openfoam.tar.gz
- - path: multiple-perpendicular-flaps
+ - &multiple-perpendicular-flaps_fluid-openfoam_solid-upstream-dealii_solid-downstream-dealii
+ path: multiple-perpendicular-flaps
case_combination:
- fluid-openfoam
- solid-upstream-dealii
- solid-downstream-dealii
- reference_result: ./perpendicular-flap/reference-results/fluid-openfoam_solid-upstream-dealii_solid-downstream-dealii.tar.gz
- elastic_tube_1d_test:
+ max_time: 0.1
+ reference_result: ./multiple-perpendicular-flaps/reference-results/fluid-openfoam_solid-upstream-dealii_solid-downstream-dealii.tar.gz
+
+ oscillator:
tutorials:
- - path: elastic-tube-1d
- case_combination:
- - fluid-cpp
- - solid-cpp
- reference_result: ./elastic-tube-1d/reference-results/fluid-cpp_solid-cpp.tar.gz
- - path: elastic-tube-1d
- case_combination:
- - fluid-python
- - solid-python
- reference_result: ./elastic-tube-1d/reference-results/fluid-python_solid-python.tar.gz
- - path: elastic-tube-1d
- case_combination:
- - fluid-cpp
- - solid-python
- reference_result: ./elastic-tube-1d/reference-results/fluid-cpp_solid-python.tar.gz
- release_test:
+ - &oscillator_mass-left-fmi_mass-right-fmi
+ path: oscillator
+ case_combination:
+ - mass-left-fmi
+ - mass-right-fmi
+ reference_result: ./oscillator/reference-results/mass-left-fmi_mass-right-fmi.tar.gz
+ - &oscillator_mass-left-python_mass-right-python
+ path: oscillator
+ case_combination:
+ - mass-left-python
+ - mass-right-python
+ reference_result: ./oscillator/reference-results/mass-left-python_mass-right-python.tar.gz
+
+ oscillator-overlap:
+ tutorials:
+ - &oscillator-overlap_mass-left-python_mass-right-python
+ path: oscillator-overlap
+ case_combination:
+ - mass-left-python
+ - mass-right-python
+ reference_result: ./oscillator-overlap/reference-results/mass-left-python_mass-right-python.tar.gz
+
+ partitioned-backwards-facing-step:
+ tutorials:
+ - &partitioned-backwards-facing-step_fluid1-openfoam_fluid2-openfoam
+ path: partitioned-backwards-facing-step
+ case_combination:
+ - fluid1-openfoam
+ - fluid2-openfoam
+ max_time: 0.5
+ reference_result: ./partitioned-backwards-facing-step/reference-results/fluid1-openfoam_fluid2-openfoam.tar.gz
+
+ partitioned-elastic-beam:
+ tutorials:
+ - &partitioned-elastic-beam_dirichlet-calculix_neumann-calculix
+ path: partitioned-elastic-beam
+ case_combination:
+ - dirichlet-calculix
+ - neumann-calculix
+ max_time_windows: 10
+ reference_result: ./partitioned-elastic-beam/reference-results/dirichlet-calculix_neumann-calculix.tar.gz
+
+ partitioned-heat-conduction:
+ tutorials:
+ - &partitioned-heat-conduction_dirichlet-fenics_neumann-fenics
+ path: partitioned-heat-conduction
+ case_combination:
+ - dirichlet-fenics
+ - neumann-fenics
+ max_time: 0.3
+ reference_result: ./partitioned-heat-conduction/reference-results/dirichlet-fenics_neumann-fenics.tar.gz
+ - &partitioned-heat-conduction_dirichlet-fenicsx_neumann-fenicsx
+ path: partitioned-heat-conduction
+ case_combination:
+ - dirichlet-fenicsx
+ - neumann-fenicsx
+ max_time: 0.3
+ reference_result: ./partitioned-heat-conduction/reference-results/dirichlet-fenicsx_neumann-fenicsx.tar.gz
+ - &partitioned-heat-conduction_dirichlet-nutils_neumann-nutils
+ path: partitioned-heat-conduction
+ case_combination:
+ - dirichlet-nutils
+ - neumann-nutils
+ max_time: 0.3
+ reference_result: ./partitioned-heat-conduction/reference-results/dirichlet-nutils_neumann-nutils.tar.gz
+ - &partitioned-heat-conduction_dirichlet-openfoam_neumann-openfoam
+ path: partitioned-heat-conduction
+ case_combination:
+ - dirichlet-openfoam
+ - neumann-openfoam
+ max_time: 0.3
+ reference_result: ./partitioned-heat-conduction/reference-results/dirichlet-openfoam_neumann-openfoam.tar.gz
+
+ partitioned-heat-conduction-3d:
tutorials:
- - *quickstart
- - path: elastic-tube-1d
+ - &partitioned-heat-conduction-3d_dirichlet-fenicsx_neumann-fenicsx
+ path: partitioned-heat-conduction-3d
+ case_combination:
+ - dirichlet-fenicsx
+ - neumann-fenicsx
+ max_time: 0.3
+ reference_result: ./partitioned-heat-conduction-3d/reference-results/dirichlet-fenicsx_neumann-fenicsx.tar.gz
+
+ partitioned-heat-conduction-complex:
+ tutorials:
+ - &partitioned-heat-conduction-complex_dirichlet-fenics_neumann-fenics
+ path: partitioned-heat-conduction-complex
+ case_combination:
+ - dirichlet-fenics
+ - neumann-fenics
+ reference_result: ./partitioned-heat-conduction-complex/reference-results/dirichlet-fenics_neumann-fenics.tar.gz
+
+ partitioned-heat-conduction-direct:
+ tutorials:
+ - &partitioned-heat-conduction-direct_dirichlet-nutils_neumann-nutils
+ path: partitioned-heat-conduction-direct
+ case_combination:
+ - dirichlet-nutils
+ - neumann-nutils
+ max_time: 0.3
+ reference_result: ./partitioned-heat-conduction-direct/reference-results/dirichlet-nutils_neumann-nutils.tar.gz
+
+ partitioned-heat-conduction-overlap:
+ tutorials:
+ - &partitioned-heat-conduction-overlap_left-fenics_right-fenics
+ path: partitioned-heat-conduction-overlap
+ case_combination:
+ - left-fenics
+ - right-fenics
+ reference_result: ./partitioned-heat-conduction-overlap/reference-results/left-fenics_right-fenics.tar.gz
+
+ partitioned-pipe:
+ tutorials:
+ - &partitioned-pipe_fluid1-openfoam-pimplefoam_fluid2-openfoam-pimplefoam
+ path: partitioned-pipe
+ case_combination:
+ - fluid1-openfoam-pimplefoam
+ - fluid2-openfoam-pimplefoam
+ max_time: 0.1
+ reference_result: ./partitioned-pipe/reference-results/fluid1-openfoam-pimplefoam_fluid2-openfoam-pimplefoam.tar.gz
+ - &partitioned-pipe_fluid1-openfoam-sonicliquidfoam_fluid2-openfoam-sonicliquidfoam
+ path: partitioned-pipe
+ case_combination:
+ - fluid1-openfoam-sonicliquidfoam
+ - fluid2-openfoam-sonicliquidfoam
+ max_time: 0.1
+ reference_result: ./partitioned-pipe/reference-results/fluid1-openfoam-sonicliquidfoam_fluid2-openfoam-sonicliquidfoam.tar.gz
+
+ partitioned-pipe-multiscale:
+ tutorials:
+ - &partitioned-pipe-multiscale_fluid1d-left-nutils_fluid3d-right-openfoam
+ path: partitioned-pipe-multiscale
+ case_combination:
+ - fluid1d-left-nutils
+ - fluid3d-right-openfoam
+ max_time: 0.05
+ reference_result: ./partitioned-pipe-multiscale/reference-results/fluid1d-left-nutils_fluid3d-right-openfoam.tar.gz
+ # More case combinations are possible, but they requite calling set-case.sh
+
+ partitioned-pipe-two-phase:
+ tutorials:
+ - &partitioned-pipe-two-phase_fluid1-openfoam_fluid2-openfoam
+ path: partitioned-pipe-two-phase
+ case_combination:
+ - fluid1-openfoam
+ - fluid2-openfoam
+ max_time: 0.1
+ reference_result: ./partitioned-pipe-two-phase/reference-results/fluid1-openfoam_fluid2-openfoam.tar.gz
+
+ perpendicular-flap:
+ tutorials:
+ - &perpendicular-flap_fluid-fake_solid-fake
+ path: perpendicular-flap
case_combination:
- - fluid-cpp
- - solid-cpp
- reference_result: ./elastic-tube-1d/reference-results/fluid-cpp_solid-cpp.tar.gz
- - path: elastic-tube-1d
+ - fluid-fake
+ - solid-fake
+ max_time: 0.1
+ reference_result: ./perpendicular-flap/reference-results/fluid-fake_solid-fake.tar.gz
+ - &perpendicular-flap_fluid-nutils_solid-calculix
+ path: perpendicular-flap
case_combination:
- - fluid-python
- - solid-python
- reference_result: ./elastic-tube-1d/reference-results/fluid-python_solid-python.tar.gz
- - path: elastic-tube-1d
+ - fluid-nutils
+ - solid-calculix
+ max_time: 0.1
+ timeout: 1200
+ reference_result: ./perpendicular-flap/reference-results/fluid-nutils_solid-calculix.tar.gz
+ - &perpendicular-flap_fluid-openfoam_solid-calculix
+ path: perpendicular-flap
case_combination:
- - fluid-cpp
- - solid-python
- reference_result: ./elastic-tube-1d/reference-results/fluid-cpp_solid-python.tar.gz
- - path: flow-over-heated-plate
+ - fluid-openfoam
+ - solid-calculix
+ reference_result: ./perpendicular-flap/reference-results/fluid-openfoam_solid-calculix.tar.gz
+ - &perpendicular-flap_fluid-openfoam_solid-dealii
+ path: perpendicular-flap
case_combination:
- fluid-openfoam
- - solid-nutils
- reference_result: ./flow-over-heated-plate/reference-results/fluid-openfoam_solid-nutils.tar.gz
- - path: flow-over-heated-plate
+ - solid-dealii
+ reference_result: ./perpendicular-flap/reference-results/fluid-openfoam_solid-dealii.tar.gz
+ - &perpendicular-flap_fluid-openfoam_solid-fenics
+ path: perpendicular-flap
case_combination:
- fluid-openfoam
- solid-fenics
- reference_result: ./flow-over-heated-plate/reference-results/fluid-openfoam_solid-fenics.tar.gz
- - path: flow-over-heated-plate
+ max_time: 0.1
+ reference_result: ./perpendicular-flap/reference-results/fluid-openfoam_solid-fenics.tar.gz
+ - &perpendicular-flap_fluid-openfoam_solid-nutils
+ path: perpendicular-flap
case_combination:
- fluid-openfoam
- - solid-openfoam
- reference_result: ./flow-over-heated-plate/reference-results/fluid-openfoam_solid-openfoam.tar.gz
- - path: perpendicular-flap
+ - solid-nutils
+ max_time: 0.1
+ reference_result: ./perpendicular-flap/reference-results/fluid-openfoam_solid-nutils.tar.gz
+ - &perpendicular-flap_fluid-openfoam_solid-openfoam
+ path: perpendicular-flap
case_combination:
- fluid-openfoam
- - solid-calculix
- reference_result: ./perpendicular-flap/reference-results/fluid-openfoam_solid-calculix.tar.gz
- - path: perpendicular-flap
+ - solid-openfoam
+ max_time: 0.03
+ reference_result: ./perpendicular-flap/reference-results/fluid-openfoam_solid-openfoam.tar.gz
+ - &perpendicular-flap_fluid-su2_solid-fenics
+ path: perpendicular-flap
case_combination:
- fluid-su2
- solid-fenics
+ max_time: 0.1
reference_result: ./perpendicular-flap/reference-results/fluid-su2_solid-fenics.tar.gz
- - path: perpendicular-flap
+
+ quickstart:
+ tutorials:
+ - &quickstart_openfoam_cpp
+ path: quickstart
case_combination:
- fluid-openfoam
- - solid-dealii
- reference_result: ./perpendicular-flap/reference-results/fluid-openfoam_solid-dealii.tar.gz
- - path: multiple-perpendicular-flaps
+ - solid-cpp
+ reference_result: ./quickstart/reference-results/fluid-openfoam_solid-cpp.tar.gz
+
+ resonant-circuit:
+ tutorials:
+ - &resonant-circuit_capacitor-python_coil-python
+ path: resonant-circuit
+ case_combination:
+ - capacitor-python
+ - coil-python
+ reference_result: ./resonant-circuit/reference-results/capacitor-python_coil-python.tar.gz
+
+ turek-hron-fsi3:
+ tutorials:
+ - &turek-hron-fsi3_fluid-nutils_solid-nutils
+ path: turek-hron-fsi3
+ case_combination:
+ - fluid-nutils
+ - solid-nutils
+ max_time: 0.003
+ timeout: 1200
+ reference_result: ./turek-hron-fsi3/reference-results/fluid-nutils_solid-nutils.tar.gz
+ - &turek-hron-fsi3_fluid-openfoam_solid-dealii
+ path: turek-hron-fsi3
case_combination:
- fluid-openfoam
- - solid-upstream-dealii
- - solid-downstream-dealii
- reference_result: ./perpendicular-flap/reference-results/fluid-openfoam_solid-upstream-dealii_solid-downstream-dealii.tar.gz
- - *heat_exchanger_simplified
- - path: free-flow-over-porous-media
+ - solid-dealii
+ max_time: 0.003
+ reference_result: ./turek-hron-fsi3/reference-results/fluid-openfoam_solid-dealii.tar.gz
+
+ two-scale-heat-conduction:
+ tutorials:
+ - &two-scale-heat-conduction_macro-dumux_micro-dumux
+ path: two-scale-heat-conduction
case_combination:
- - free-flow-dumux
- - porous-media-dumux
- reference_result: ./free-flow-over-porous-media/reference-results/free-flow-dumux_porous-media-dumux.tar.gz
+ - macro-dumux
+ - micro-dumux
+ reference_result: ./two-scale-heat-conduction/reference-results/macro-dumux_micro-dumux.tar.gz # Too small values, expected to fail the comparisons.
+ - &two-scale-heat-conduction_macro-nutils_micro-nutils
+ path: two-scale-heat-conduction
+ case_combination:
+ - macro-nutils
+ - micro-nutils
+ max_time: 0.05
+ reference_result: ./two-scale-heat-conduction/reference-results/macro-nutils_micro-nutils.tar.gz # Too small values, expected to fail the comparisons.
+
+ volume-coupled-diffusion:
+ tutorials:
+ - &volume-coupled-diffusion_source-fenics_drain-fenics
+ path: volume-coupled-diffusion
+ case_combination:
+ - source-fenics
+ - drain-fenics
+ max_time: 1.0
+ reference_result: ./volume-coupled-diffusion/reference-results/source-fenics_drain-fenics.tar.gz
+
+ volume-coupled-flow:
+ tutorials:
+ - &volume-coupled-flow_fluid-openfoam_source-nutils
+ path: volume-coupled-flow
+ case_combination:
+ - fluid-openfoam
+ - source-nutils
+ max_time: 0.05
+ reference_result: ./volume-coupled-flow/reference-results/fluid-openfoam_source-nutils.tar.gz
+
+ water-hammer:
+ tutorials:
+ - &water-hammer_fluid1d-left-nutils_fluid3d-right-openfoam
+ path: water-hammer
+ case_combination:
+ - fluid1d-left-nutils
+ - fluid3d-right-openfoam
+ max_time: 0.05
+ reference_result: ./water-hammer/reference-results/fluid1d-left-nutils_fluid3d-right-openfoam.tar.gz
+ # More case combinations are possible, but they requite calling set-case.sh
+
+ wolf-sheep-soil-creep:
+ tutorials:
+ - &wolf-sheep-soil-creep_soil-creep-landlab_wolf-sheep-grass-mesa
+ path: wolf-sheep-soil-creep
+ case_combination:
+ - soil-creep-landlab
+ - wolf-sheep-grass-mesa
+ max_time: 20
+ reference_result: ./wolf-sheep-soil-creep/reference-results/soil-creep-landlab_wolf-sheep-grass-mesa.tar.gz
+
+#####################################################################
+## Test suites referring to the test suites defined above
+
+ release:
+ tutorials:
+ - *breaking-dam-2d_fluid-openfoam_solid-calculix
+ - *channel-transport_fluid-openfoam_transport-nutils
+ - *channel-transport-reaction_fluid-fenics_chemical-fenics
+ - *channel-transport-particles_fluid-openfoam_particles-mercurydpm
+ - *channel-transport-particles_fluid-nutils_particles-mercurydpm
+ - *elastic-tube-1d_fluid-cpp_solid-cpp
+ - *elastic-tube-1d_fluid-cpp_solid-python
+ - *elastic-tube-1d_fluid-fortran_solid-fortran
+ - *elastic-tube-1d_fluid-fortran-module_solid-fortran-module
+ - *elastic-tube-1d_fluid-python_solid-python
+ - *elastic-tube-3d_fluid-openfoam_solid-calculix
+ - *flow-around-controlled-moving-cylinder_controller-fmi_fluid-openfoam_solid-python
+ - *flow-over-heated-plate_fluid-openfoam_solid-fenics
+ - *flow-over-heated-plate_fluid-openfoam_solid-fenicsx
+ - *flow-over-heated-plate_fluid-openfoam_solid-nutils
+ - *flow-over-heated-plate_fluid-openfoam_solid-openfoam
+ - *flow-over-heated-plate_fluid-su2_solid-openfoam
+ - *flow-over-heated-plate-nearest-projection_fluid-openfoam_solid-openfoam
+ - *flow-over-heated-plate-partitioned-flow_fluid1-openfoam_fluid2-openfoam_solid-openfoam
+ - *flow-over-heated-plate-two-meshes_fluid-openfoam_solid-calculix
+ - *free-flow-over-porous-media_free-flow-dumux_porous-media-dumux
+ - *heat-exchanger_fluid-inner-openfoam_solid-calculix_fluid-outer-openfoam
+ - *heat-exchanger-simplified_fluid-top-openfoam_fluid-bottom-openfoam_solid-calculix
+ - *multiple-perpendicular-flaps_fluid-openfoam_solid-upstream-dealii_solid-downstream-dealii
+ - *oscillator_mass-left-fmi_mass-right-fmi
+ - *oscillator_mass-left-python_mass-right-python
+ - *oscillator-overlap_mass-left-python_mass-right-python
+ - *partitioned-backwards-facing-step_fluid1-openfoam_fluid2-openfoam
+ - *partitioned-elastic-beam_dirichlet-calculix_neumann-calculix
+ - *partitioned-heat-conduction_dirichlet-fenics_neumann-fenics
+ - *partitioned-heat-conduction_dirichlet-fenicsx_neumann-fenicsx
+ - *partitioned-heat-conduction_dirichlet-openfoam_neumann-openfoam
+ - *partitioned-heat-conduction-3d_dirichlet-fenicsx_neumann-fenicsx
+ - *partitioned-heat-conduction-complex_dirichlet-fenics_neumann-fenics
+ - *partitioned-heat-conduction-direct_dirichlet-nutils_neumann-nutils
+ - *partitioned-heat-conduction-overlap_left-fenics_right-fenics
+ - *partitioned-pipe_fluid1-openfoam-pimplefoam_fluid2-openfoam-pimplefoam
+ - *partitioned-pipe_fluid1-openfoam-sonicliquidfoam_fluid2-openfoam-sonicliquidfoam
+ - *partitioned-pipe-multiscale_fluid1d-left-nutils_fluid3d-right-openfoam
+ - *partitioned-pipe-two-phase_fluid1-openfoam_fluid2-openfoam
+ - *perpendicular-flap_fluid-fake_solid-fake
+ - *perpendicular-flap_fluid-openfoam_solid-calculix
+ - *perpendicular-flap_fluid-openfoam_solid-dealii
+ - *perpendicular-flap_fluid-openfoam_solid-fenics
+ - *perpendicular-flap_fluid-openfoam_solid-openfoam
+ - *perpendicular-flap_fluid-su2_solid-fenics
+ - *quickstart_openfoam_cpp
+ - *resonant-circuit_capacitor-python_coil-python
+ - *turek-hron-fsi3_fluid-openfoam_solid-dealii
+ - *volume-coupled-diffusion_source-fenics_drain-fenics
+ - *volume-coupled-flow_fluid-openfoam_source-nutils
+ - *water-hammer_fluid1d-left-nutils_fluid3d-right-openfoam
+ - *wolf-sheep-soil-creep_soil-creep-landlab_wolf-sheep-grass-mesa
+
+ # These tests take longer to run. They are available, but not regularly executed.
+ extra:
+ tutorials:
+ - *channel-transport_fluid-nutils_transport-nutils
+ - *partitioned-heat-conduction_dirichlet-nutils_neumann-nutils
+ - *perpendicular-flap_fluid-nutils_solid-calculix
+ - *perpendicular-flap_fluid-openfoam_solid-nutils
+ - *turek-hron-fsi3_fluid-nutils_solid-nutils
+
+ expected-to-fail:
+ tutorials:
+ - *elastic-tube-3d_fluid-openfoam_solid-fenics # too small values to compare
+ - *two-scale-heat-conduction_macro-dumux_micro-dumux # too small values to compare
+
+ # A selection of tests that cover a wide range of main features, meant for quicker CI executions
+ precice:
+ tutorials:
+ - *quickstart_openfoam_cpp # serial-explicit, RBF
+ - *channel-transport_fluid-openfoam_transport-nutils # parallel-explicit, RBF, python bindings
+ - *flow-over-heated-plate_fluid-openfoam_solid-openfoam # serial-implicit (Aitken), nearest-neighbor
+ - *flow-over-heated-plate-nearest-projection_fluid-openfoam_solid-openfoam # serial-implicit (IQN-ILS), nearest-projection
+ - *elastic-tube-1d_fluid-cpp_solid-cpp # serial-implicit (IQN-ILS), nearest-neighbor
+ - *partitioned-pipe-multiscale_fluid1d-left-nutils_fluid3d-right-openfoam # parallel-implicit (IQN-ILS), axial-geometric-multiscale
+ - *elastic-tube-1d_fluid-fortran-module_solid-fortran-module # integration with Fortran (module)
+ - *perpendicular-flap_fluid-openfoam_solid-calculix # integration with C
+
+ calculix-adapter:
+ tutorials:
+ - *breaking-dam-2d_fluid-openfoam_solid-calculix
+ - *elastic-tube-3d_fluid-openfoam_solid-calculix
+ - *flow-over-heated-plate-two-meshes_fluid-openfoam_solid-calculix
+ - *heat-exchanger_fluid-inner-openfoam_solid-calculix_fluid-outer-openfoam
+ - *heat-exchanger-simplified_fluid-top-openfoam_fluid-bottom-openfoam_solid-calculix
+ - *partitioned-elastic-beam_dirichlet-calculix_neumann-calculix
+ - *perpendicular-flap_fluid-openfoam_solid-calculix
+
+ dealii-adapter:
+ tutorials:
+ - *multiple-perpendicular-flaps_fluid-openfoam_solid-upstream-dealii_solid-downstream-dealii
+ - *perpendicular-flap_fluid-openfoam_solid-dealii
+ - *turek-hron-fsi3_fluid-openfoam_solid-dealii
+
+ dumux-adapter:
+ tutorials:
+ - *free-flow-over-porous-media_free-flow-dumux_porous-media-dumux
+ - *two-scale-heat-conduction_macro-dumux_micro-dumux
+
+ fenics-adapter:
+ tutorials:
+ - *channel-transport-reaction_fluid-fenics_chemical-fenics
+ - *flow-over-heated-plate_fluid-openfoam_solid-fenics
+ - *partitioned-heat-conduction_dirichlet-fenics_neumann-fenics
+ - *partitioned-heat-conduction-complex_dirichlet-fenics_neumann-fenics
+ - *partitioned-heat-conduction-overlap_left-fenics_right-fenics
+ - *perpendicular-flap_fluid-openfoam_solid-fenics
+ - *perpendicular-flap_fluid-su2_solid-fenics
+ - *volume-coupled-diffusion_source-fenics_drain-fenics
+
+ # Excluded:
+ # *elastic-tube-3d_fluid-openfoam_solid-fenics # too small values to compare
+
+ fenicsx-adapter:
+ tutorials:
+ - *flow-over-heated-plate_fluid-openfoam_solid-fenicsx
+ - *partitioned-heat-conduction_dirichlet-fenicsx_neumann-fenicsx
+ - *partitioned-heat-conduction-3d_dirichlet-fenicsx_neumann-fenicsx
+
+ fmi-runner:
+ tutorials:
+ - *oscillator_mass-left-fmi_mass-right-fmi
+
+ fortran-module:
+ tutorials:
+ - *elastic-tube-1d_fluid-fortran-module_solid-fortran-module
+
+ mercurydpm-adapter:
+ tutorials:
+ - *channel-transport-particles_fluid-openfoam_particles-mercurydpm
+ - *channel-transport-particles_fluid-nutils_particles-mercurydpm
+
+ micro-manager:
+ tutorials:
+ - *two-scale-heat-conduction_macro-dumux_micro-dumux # too small values to compare
+ - *two-scale-heat-conduction_macro-nutils_micro-nutils # too small values to compare
+
+ nutils-adapter: # Not a repository
+ tutorials:
+ - *channel-transport_fluid-openfoam_transport-nutils
+ - *channel-transport_fluid-nutils_transport-nutils
+ - *channel-transport-particles_fluid-nutils_particles-mercurydpm
+ - *flow-over-heated-plate_fluid-openfoam_solid-nutils
+ - *partitioned-heat-conduction_dirichlet-nutils_neumann-nutils
+ - *partitioned-heat-conduction-direct_dirichlet-nutils_neumann-nutils
+ - *partitioned-pipe-multiscale_fluid1d-left-nutils_fluid3d-right-openfoam
+ - *perpendicular-flap_fluid-nutils_solid-calculix
+ - *turek-hron-fsi3_fluid-nutils_solid-nutils
+ - *volume-coupled-flow_fluid-openfoam_source-nutils
+ - *water-hammer_fluid1d-left-nutils_fluid3d-right-openfoam
+
+ # Excluded:
+ # *two-scale-heat-conduction_macro-nutils_micro-nutils # too small values to compare
+
+ openfoam-adapter:
+ tutorials:
+ - *breaking-dam-2d_fluid-openfoam_solid-calculix
+ - *channel-transport_fluid-openfoam_transport-nutils
+ - *channel-transport-particles_fluid-openfoam_particles-mercurydpm
+ - *elastic-tube-3d_fluid-openfoam_solid-calculix
+ - *flow-around-controlled-moving-cylinder_controller-fmi_fluid-openfoam_solid-python
+ - *flow-over-heated-plate_fluid-openfoam_solid-fenics
+ - *flow-over-heated-plate_fluid-openfoam_solid-nutils
+ - *flow-over-heated-plate_fluid-openfoam_solid-openfoam
+ - *flow-over-heated-plate-nearest-projection_fluid-openfoam_solid-openfoam
+ - *flow-over-heated-plate-partitioned-flow_fluid1-openfoam_fluid2-openfoam_solid-openfoam
+ - *flow-over-heated-plate-two-meshes_fluid-openfoam_solid-calculix
+ - *flow-over-heated-plate_fluid-su2_solid-openfoam
+ - *heat-exchanger_fluid-inner-openfoam_solid-calculix_fluid-outer-openfoam
+ - *heat-exchanger-simplified_fluid-top-openfoam_fluid-bottom-openfoam_solid-calculix
+ - *multiple-perpendicular-flaps_fluid-openfoam_solid-upstream-dealii_solid-downstream-dealii
+ - *partitioned-backwards-facing-step_fluid1-openfoam_fluid2-openfoam
+ - *partitioned-heat-conduction_dirichlet-openfoam_neumann-openfoam
+ - *partitioned-pipe_fluid1-openfoam-pimplefoam_fluid2-openfoam-pimplefoam
+ - *partitioned-pipe_fluid1-openfoam-sonicliquidfoam_fluid2-openfoam-sonicliquidfoam
+ - *partitioned-pipe-multiscale_fluid1d-left-nutils_fluid3d-right-openfoam
+ - *partitioned-pipe-two-phase_fluid1-openfoam_fluid2-openfoam
+ - *perpendicular-flap_fluid-openfoam_solid-calculix
+ - *perpendicular-flap_fluid-openfoam_solid-dealii
+ - *perpendicular-flap_fluid-openfoam_solid-fenics
+ - *perpendicular-flap_fluid-openfoam_solid-openfoam
+ - *turek-hron-fsi3_fluid-openfoam_solid-dealii
+ - *quickstart_openfoam_cpp
+ - *volume-coupled-flow_fluid-openfoam_source-nutils
+ - *water-hammer_fluid1d-left-nutils_fluid3d-right-openfoam
+
+ # Excluded:
+ # *elastic-tube-3d_fluid-openfoam_solid-fenics # too small values to compare
+
+ su2-adapter:
+ tutorials:
+ - *flow-over-heated-plate_fluid-su2_solid-openfoam
+ - *perpendicular-flap_fluid-su2_solid-fenics
+
+ # A test suite used for the system tests development
+ system-tests-dev:
+ tutorials:
+ - *elastic-tube-1d_fluid-cpp_solid-cpp
+
+ selected:
+ tutorials:
+ - *elastic-tube-1d_fluid-python_solid-python
\ No newline at end of file
diff --git a/tools/tests/update_requirements_reference.py b/tools/tests/update_requirements_reference.py
new file mode 100644
index 000000000..e6c6a2ae0
--- /dev/null
+++ b/tools/tests/update_requirements_reference.py
@@ -0,0 +1,116 @@
+#!/usr/bin/env python3
+"""
+Update requirements-reference.txt with pinned versions from reference_versions.yaml.
+
+This script reads PYTHON_BINDINGS_REF from reference_versions.yaml and generates
+a requirements-reference.txt with pyprecice pinned to the corresponding version.
+Other common packages (numpy, matplotlib, setuptools) use fixed versions known
+to work with the tutorials.
+
+Run from tools/tests/:
+ python3 update_requirements_reference.py
+
+Or to regenerate from a pip freeze (e.g. from Docker):
+ pip freeze | python3 update_requirements_reference.py --from-freeze
+"""
+import argparse
+import re
+import sys
+from pathlib import Path
+
+REFERENCE_VERSIONS = Path(__file__).parent / "reference_versions.yaml"
+REQUIREMENTS_REF = Path(__file__).parent / "requirements-reference.txt"
+
+# Default pinned versions for common packages (fallback when not using --from-freeze)
+DEFAULTS = {
+ "matplotlib": "3.9.0",
+ "numpy": "1.26.4",
+ "nutils": "7.2",
+ "pyprecice": None, # From reference_versions.yaml
+ "setuptools": ">=69.0.0",
+}
+
+# Packages to include (in order)
+PACKAGES = ["matplotlib", "numpy", "nutils", "pyprecice", "setuptools"]
+
+
+def get_pyprecice_version_from_ref(ref: str) -> str:
+ """Convert PYTHON_BINDINGS_REF (e.g. v3.2.0) to pyprecice version (3.2.0)."""
+ return ref.lstrip("v").strip()
+
+
+def load_reference_versions() -> str:
+ """Load PYTHON_BINDINGS_REF from reference_versions.yaml."""
+ text = REFERENCE_VERSIONS.read_text()
+ for line in text.splitlines():
+ if "PYTHON_BINDINGS_REF" in line and ":" in line:
+ match = re.search(r'["\']([^"\']+)["\']', line)
+ if match:
+ return match.group(1)
+ raise ValueError("PYTHON_BINDINGS_REF not found in reference_versions.yaml")
+
+
+def parse_freezed_packages(freezed: str) -> dict[str, str]:
+ """Parse pip freeze output into {package: version}."""
+ result = {}
+ for line in freezed.strip().splitlines():
+ line = line.strip()
+ if not line or line.startswith("#"):
+ continue
+ if "==" in line:
+ pkg, ver = line.split("==", 1)
+ result[pkg.lower()] = f"=={ver.strip()}"
+ elif "===" in line:
+ pkg, ver = line.split("===", 1)
+ result[pkg.lower()] = f"=={ver.strip()}"
+ return result
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser(
+ description="Update requirements-reference.txt from reference_versions.yaml"
+ )
+ parser.add_argument(
+ "--from-freeze",
+ action="store_true",
+ help="Read pip freeze from stdin and use those versions for known packages",
+ )
+ args = parser.parse_args()
+
+ pyprecice_ref = load_reference_versions()
+ pyprecice_ver = get_pyprecice_version_from_ref(pyprecice_ref)
+
+ if args.from_freeze:
+ freezed = parse_freezed_packages(sys.stdin.read())
+ versions = {}
+ for pkg in PACKAGES:
+ if pkg.lower() in freezed:
+ versions[pkg] = freezed[pkg.lower()]
+ elif pkg == "pyprecice":
+ versions[pkg] = f"=={pyprecice_ver}"
+ elif DEFAULTS.get(pkg):
+ versions[pkg] = (
+ DEFAULTS[pkg] if DEFAULTS[pkg].startswith(("==", ">=", "~=")) else f"=={DEFAULTS[pkg]}"
+ )
+ else:
+ DEFAULTS["pyprecice"] = pyprecice_ver
+ versions = {
+ pkg: f"=={ver}" if ver and not ver.startswith(("==", ">=", "~=")) else (ver or "")
+ for pkg, ver in DEFAULTS.items()
+ }
+ versions["pyprecice"] = f"=={pyprecice_ver}"
+
+ header = """# Pinned Python dependency versions for reproducible system tests and distributions.
+# Generated from reference_versions.yaml (PYTHON_BINDINGS_REF). Update at each release.
+# Run: python3 update_requirements_reference.py
+#
+# See tools/tests/README.md for how to update this file.
+
+"""
+ lines = [f"{pkg}{versions.get(pkg, '')}\n" for pkg in PACKAGES if pkg in versions]
+ REQUIREMENTS_REF.write_text(header + "".join(lines))
+ print(f"Wrote {REQUIREMENTS_REF} (pyprecice from {pyprecice_ref})")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tools/tests/validate_requirements_reference.py b/tools/tests/validate_requirements_reference.py
new file mode 100644
index 000000000..870f53b8c
--- /dev/null
+++ b/tools/tests/validate_requirements_reference.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python3
+"""
+Validate that requirements-reference.txt exists and pyprecice version
+matches PYTHON_BINDINGS_REF in reference_versions.yaml.
+
+Exit 0 on success, 1 on failure.
+"""
+import re
+import sys
+from pathlib import Path
+
+TOOLS_TESTS = Path(__file__).parent
+REFERENCE_VERSIONS = TOOLS_TESTS / "reference_versions.yaml"
+REQUIREMENTS_REF = TOOLS_TESTS / "requirements-reference.txt"
+
+
+def main() -> int:
+ if not REQUIREMENTS_REF.exists():
+ print(f"ERROR: {REQUIREMENTS_REF} not found. Run update_requirements_reference.py.", file=sys.stderr)
+ return 1
+
+ # Load PYTHON_BINDINGS_REF
+ ref_text = REFERENCE_VERSIONS.read_text()
+ ref_match = re.search(r'PYTHON_BINDINGS_REF:\s*["\']([^"\']+)["\']', ref_text)
+ if not ref_match:
+ print("ERROR: PYTHON_BINDINGS_REF not found in reference_versions.yaml", file=sys.stderr)
+ return 1
+
+ expected_ver = ref_match.group(1).lstrip("v").strip()
+
+ # Parse pyprecice from requirements-reference.txt
+ req_text = REQUIREMENTS_REF.read_text()
+ precice_match = re.search(r"pyprecice\s*==\s*([\w.]+)", req_text)
+ if not precice_match:
+ print("ERROR: pyprecice not found in requirements-reference.txt", file=sys.stderr)
+ return 1
+
+ actual_ver = precice_match.group(1).strip()
+ if actual_ver != expected_ver:
+ print(
+ f"ERROR: pyprecice version mismatch: requirements-reference.txt has {actual_ver}, "
+ f"reference_versions.yaml PYTHON_BINDINGS_REF has {ref_match.group(1)}. "
+ "Run: python3 update_requirements_reference.py",
+ file=sys.stderr,
+ )
+ return 1
+
+ print(f"OK: requirements-reference.txt pyprecice=={actual_ver} matches reference_versions.yaml")
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/tools/validate_requirements_reference.py b/tools/validate_requirements_reference.py
new file mode 100644
index 000000000..ecb0bbc70
--- /dev/null
+++ b/tools/validate_requirements_reference.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python3
+"""
+Validate that requirements-reference.txt matches tutorial requirements.txt constraints.
+
+Delegates to report_tutorial_requirements.py --check.
+"""
+import subprocess
+import sys
+from pathlib import Path
+
+SCRIPT = Path(__file__).parent / "report_tutorial_requirements.py"
+
+
+def main() -> int:
+ result = subprocess.run([sys.executable, str(SCRIPT), "--check"], check=False)
+ return result.returncode
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/tools/visualize-configs.sh b/tools/visualize-configs.sh
index bf430eb66..e56a110ae 100755
--- a/tools/visualize-configs.sh
+++ b/tools/visualize-configs.sh
@@ -30,9 +30,16 @@ visualize_config(){
export -f visualize_config
-python3 -m venv .venv
-. .venv/bin/activate
-pip install precice-config-visualizer
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
+then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install precice-config-visualizer
+ else
+ source .venv/bin/activate
+ fi
+fi
tutorials=$(find . -maxdepth 1 -type d -not -name ".*" | sed "s/^.\///")
diff --git a/turek-hron-fsi3/README.md b/turek-hron-fsi3/README.md
index 726d83cfe..35da47df4 100644
--- a/turek-hron-fsi3/README.md
+++ b/turek-hron-fsi3/README.md
@@ -28,12 +28,12 @@ preCICE configuration (image generated using the [precice-config-visualizer](htt
Fluid participant:
* OpenFOAM (pimpleFoam). In case you are using a very old OpenFOAM version, you will need to adjust the solver to `pimpleDyMFoam` in the `Fluid/system/controlDict` file. For more information, have a look at the [OpenFOAM adapter documentation](https://precice.org/adapter-openfoam-overview.html).
-* Nutils. For more information, have a look at the [Nutils adapter documentation](https://precice.org/adapter-nutils.html). This Nutils solver requires at least Nutils v9.0. This case takes significantly longer to run than the OpenFOAM case, see [related issue](https://github.com/precice/tutorials/issues/506).
+* Nutils. For more information, have a look at the [Nutils adapter documentation](https://precice.org/adapter-nutils.html). This case takes significantly longer to run than the OpenFOAM case, see [related issue](https://github.com/precice/tutorials/issues/506).
Solid participant:
* deal.II. For more information, have a look at the [deal.II adapter documentation](https://precice.org/adapter-dealii-overview.html). This tutorial requires the nonlinear solid solver. Please copy the nonlinear solver executable to the `solid-dealii` folder or make it discoverable at runtime and update the `solid-dealii/run.sh` script.
-* Nutils. For more information, have a look at the [Nutils adapter documentation](https://precice.org/adapter-nutils.html). This Nutils solver requires at least Nutils v9.0.
+* Nutils. For more information, have a look at the [Nutils adapter documentation](https://precice.org/adapter-nutils.html).
## Running the Simulation
diff --git a/turek-hron-fsi3/fluid-nutils/requirements.txt b/turek-hron-fsi3/fluid-nutils/requirements.txt
index de8073acb..f324f08fe 100644
--- a/turek-hron-fsi3/fluid-nutils/requirements.txt
+++ b/turek-hron-fsi3/fluid-nutils/requirements.txt
@@ -1,7 +1,7 @@
-setuptools # required by nutils
+setuptools>=69.0.0 # required by nutils
nutils~=9.0
numpy >1, <2
pyprecice~=3.0
-meshio
-gmsh
-matplotlib
+meshio>=5,<6
+gmsh>=4,<5
+matplotlib>=3.5,<4
diff --git a/turek-hron-fsi3/fluid-nutils/run.sh b/turek-hron-fsi3/fluid-nutils/run.sh
index d0c4c71f9..6cc554f0f 100755
--- a/turek-hron-fsi3/fluid-nutils/run.sh
+++ b/turek-hron-fsi3/fluid-nutils/run.sh
@@ -4,11 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
python fluid.py
diff --git a/turek-hron-fsi3/metadata.yaml b/turek-hron-fsi3/metadata.yaml
new file mode 100644
index 000000000..1647e2120
--- /dev/null
+++ b/turek-hron-fsi3/metadata.yaml
@@ -0,0 +1,34 @@
+name: Turek-Hron FSI3
+path: turek-hron-fsi3 # relative to git repo
+url: https://precice.org/tutorials-turek-hron-fsi3.html
+
+participants:
+ - Fluid
+ - Solid
+
+cases:
+ fluid-openfoam:
+ participant: Fluid
+ directory: ./fluid-openfoam
+ run: ./run.sh
+ component: openfoam-adapter
+
+ fluid-nutils:
+ participant: Fluid
+ directory: ./fluid-nutils
+ run: ./run.sh
+ component: nutils-adapter
+
+ solid-dealii:
+ participant: Solid
+ directory: ./solid-dealii
+ run: ./run.sh
+ component: dealii-adapter
+
+ solid-nutils:
+ participant: Solid
+ directory: ./solid-nutils
+ run: ./run.sh
+ component: nutils-adapter
+
+
diff --git a/turek-hron-fsi3/reference-results/fluid-nutils_solid-nutils.tar.gz b/turek-hron-fsi3/reference-results/fluid-nutils_solid-nutils.tar.gz
new file mode 100644
index 000000000..85380e20f
--- /dev/null
+++ b/turek-hron-fsi3/reference-results/fluid-nutils_solid-nutils.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c50c0c5d35cf0808ad33ea068ba94b7eb1d9e1573c4a65991c25e98c21055fcd
+size 3868
diff --git a/turek-hron-fsi3/reference-results/fluid-openfoam_solid-dealii.tar.gz b/turek-hron-fsi3/reference-results/fluid-openfoam_solid-dealii.tar.gz
new file mode 100644
index 000000000..768dc47a0
--- /dev/null
+++ b/turek-hron-fsi3/reference-results/fluid-openfoam_solid-dealii.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:be0303d3b9113989cef36ec211acbecf37c09d8720160f15ef2a267c173eeb01
+size 36332
diff --git a/turek-hron-fsi3/reference-results/reference_results.metadata b/turek-hron-fsi3/reference-results/reference_results.metadata
new file mode 100644
index 000000000..9bc293c98
--- /dev/null
+++ b/turek-hron-fsi3/reference-results/reference_results.metadata
@@ -0,0 +1,72 @@
+
+
+# Reference Results
+
+This file contains an overview of the results over the reference results as well as the arguments used to generate them.
+We also include some information on the machine used to generate them
+
+## List of files
+
+| name | time | sha256 |
+|------|------|-------|
+| fluid-openfoam_solid-dealii.tar.gz | 2026-05-29 13:59:53 | be0303d3b9113989cef36ec211acbecf37c09d8720160f15ef2a267c173eeb01 |
+| fluid-nutils_solid-nutils.tar.gz | 2026-05-29 13:59:53 | c50c0c5d35cf0808ad33ea068ba94b7eb1d9e1573c4a65991c25e98c21055fcd |
+
+## List of arguments used to generate the files
+
+| name | value |
+|------|------|
+| PLATFORM | ubuntu_2404 |
+| CALCULIX_VERSION | 2.20 |
+| DUNE_VERSION | 2.9 |
+| DUMUX_VERSION | 3.7 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | 33a2563 |
+| PRECICE_PRESET | production-audit |
+| PRECICE_UID | 1003 |
+| PRECICE_GID | 1003 |
+## Information about the machine
+
+### uname -a
+
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+
+
+### lscpu
+
+Architecture: x86_64
+CPU op-mode(s): 32-bit, 64-bit
+Address sizes: 45 bits physical, 48 bits virtual
+Byte Order: Little Endian
+CPU(s): 4
+On-line CPU(s) list: 0-3
+Vendor ID: GenuineIntel
+Model name: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz
+CPU family: 6
+Model: 85
+Thread(s) per core: 1
+Core(s) per socket: 1
+Socket(s): 4
+Stepping: 4
+BogoMIPS: 4199.99
+Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat pku ospke md_clear flush_l1d arch_capabilities
+Hypervisor vendor: VMware
+Virtualization type: full
+L1d cache: 128 KiB (4 instances)
+L1i cache: 128 KiB (4 instances)
+L2 cache: 4 MiB (4 instances)
+L3 cache: 88 MiB (4 instances)
+NUMA node(s): 1
+NUMA node0 CPU(s): 0-3
diff --git a/turek-hron-fsi3/solid-nutils/requirements.txt b/turek-hron-fsi3/solid-nutils/requirements.txt
index de8073acb..f324f08fe 100644
--- a/turek-hron-fsi3/solid-nutils/requirements.txt
+++ b/turek-hron-fsi3/solid-nutils/requirements.txt
@@ -1,7 +1,7 @@
-setuptools # required by nutils
+setuptools>=69.0.0 # required by nutils
nutils~=9.0
numpy >1, <2
pyprecice~=3.0
-meshio
-gmsh
-matplotlib
+meshio>=5,<6
+gmsh>=4,<5
+matplotlib>=3.5,<4
diff --git a/turek-hron-fsi3/solid-nutils/run.sh b/turek-hron-fsi3/solid-nutils/run.sh
index 2942ab3ed..08ecc9a7f 100755
--- a/turek-hron-fsi3/solid-nutils/run.sh
+++ b/turek-hron-fsi3/solid-nutils/run.sh
@@ -4,11 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
python solid.py
diff --git a/two-scale-heat-conduction/macro-nutils/requirements.txt b/two-scale-heat-conduction/macro-nutils/requirements.txt
index 7ff7b5aa1..f22e7ac25 100644
--- a/two-scale-heat-conduction/macro-nutils/requirements.txt
+++ b/two-scale-heat-conduction/macro-nutils/requirements.txt
@@ -1,4 +1,4 @@
-setuptools # required by nutils
+setuptools>=69.0.0 # required by nutils
nutils~=7.3
numpy >1, <2
pyprecice~=3.0
diff --git a/two-scale-heat-conduction/macro-nutils/run.sh b/two-scale-heat-conduction/macro-nutils/run.sh
index 3cf21c216..42703c0b0 100755
--- a/two-scale-heat-conduction/macro-nutils/run.sh
+++ b/two-scale-heat-conduction/macro-nutils/run.sh
@@ -4,11 +4,14 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
python3 macro.py richoutput=no
diff --git a/two-scale-heat-conduction/metadata.yaml b/two-scale-heat-conduction/metadata.yaml
index 75d465531..6c7c1dafb 100644
--- a/two-scale-heat-conduction/metadata.yaml
+++ b/two-scale-heat-conduction/metadata.yaml
@@ -12,9 +12,21 @@ cases:
directory: ./macro-dumux
run: ./run.sh -l /home/precice/dumux
component: dumux-adapter
+
+ macro-nutils:
+ participant: Macro
+ directory: ./macro-nutils
+ run: ./run.sh -l /home/precice/nutils
+ component: nutils-adapter
micro-dumux:
participant: Micro-Manager
directory: ./micro-dumux
run: source /home/precice/venv/bin/activate && ./run.sh -l /home/precice/dumux
component: dumux-adapter
+
+ micro-nutils:
+ participant: Micro-Manager
+ directory: ./micro-nutils
+ run: source /home/precice/venv/bin/activate && ./run.sh -l /home/precice/nutils
+ component: nutils-adapter
\ No newline at end of file
diff --git a/two-scale-heat-conduction/micro-nutils/requirements.txt b/two-scale-heat-conduction/micro-nutils/requirements.txt
index 6bcbfdaff..8256d3119 100644
--- a/two-scale-heat-conduction/micro-nutils/requirements.txt
+++ b/two-scale-heat-conduction/micro-nutils/requirements.txt
@@ -1,5 +1,5 @@
-setuptools # required by nutils
+setuptools>=69.0.0 # required by nutils
nutils~=7.3
numpy >1, <2
pyprecice~=3.0
-micro-manager-precice
+micro-manager-precice~=0.10
diff --git a/two-scale-heat-conduction/micro-nutils/run.sh b/two-scale-heat-conduction/micro-nutils/run.sh
index 4e57595db..a7de2a099 100755
--- a/two-scale-heat-conduction/micro-nutils/run.sh
+++ b/two-scale-heat-conduction/micro-nutils/run.sh
@@ -6,11 +6,14 @@ exec > >(tee --append "$LOGFILE") 2>&1
usage() { echo "Usage: cmd [-s] [-p n]" 1>&2; exit 1; }
-if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
-then
- python3 -m venv .venv
- . .venv/bin/activate
- pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
fi
# Check if no input argument was provided
diff --git a/two-scale-heat-conduction/precice-config.xml b/two-scale-heat-conduction/precice-config.xml
index e1328fda1..3ca95ad2f 100644
--- a/two-scale-heat-conduction/precice-config.xml
+++ b/two-scale-heat-conduction/precice-config.xml
@@ -1,7 +1,10 @@
-
+
diff --git a/two-scale-heat-conduction/reference-results/macro-dumux_micro-dumux.tar.gz b/two-scale-heat-conduction/reference-results/macro-dumux_micro-dumux.tar.gz
index 83a2a6c45..518abf212 100644
--- a/two-scale-heat-conduction/reference-results/macro-dumux_micro-dumux.tar.gz
+++ b/two-scale-heat-conduction/reference-results/macro-dumux_micro-dumux.tar.gz
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b08f5a2e5cf0535bc7c08bbf9ddc9dbaa875363b2c030bc0ee25de654cb7e027
-size 4788
+oid sha256:446c1aee6ec3cabd76de63838ae3cd02668b38ad72b405d5b50b19b465ea5011
+size 2270
diff --git a/two-scale-heat-conduction/reference-results/reference_results.metadata b/two-scale-heat-conduction/reference-results/reference_results.metadata
index b769e723a..585e72a3a 100644
--- a/two-scale-heat-conduction/reference-results/reference_results.metadata
+++ b/two-scale-heat-conduction/reference-results/reference_results.metadata
@@ -11,36 +11,36 @@ We also include some information on the machine used to generate them
| name | time | sha256 |
|------|------|-------|
-| macro-dumux_micro-dumux.tar.gz | 2026-05-11 07:45:27 | b08f5a2e5cf0535bc7c08bbf9ddc9dbaa875363b2c030bc0ee25de654cb7e027 |
+| macro-dumux_micro-dumux.tar.gz | 2026-05-31 01:04:27 | 446c1aee6ec3cabd76de63838ae3cd02668b38ad72b405d5b50b19b465ea5011 |
## List of arguments used to generate the files
| name | value |
|------|------|
-| PRECICE_REF | d199bb3 |
-| PRECICE_PRESET | production-audit |
-| OPENFOAM_EXECUTABLE | openfoam2312 |
-| OPENFOAM_ADAPTER_REF | v1.3.1 |
-| PYTHON_BINDINGS_REF | v3.2.0 |
-| FENICS_ADAPTER_REF | v2.2.0 |
-| TUTORIALS_REF | b18b3ef |
| PLATFORM | ubuntu_2404 |
| CALCULIX_VERSION | 2.20 |
-| CALCULIX_ADAPTER_REF | v2.20.1 |
-| SU2_VERSION | 7.5.1 |
-| SU2_ADAPTER_REF | 64d4aff |
-| DEALII_ADAPTER_REF | 02c5d18 |
| DUNE_VERSION | 2.9 |
| DUMUX_VERSION | 3.7 |
-| DUMUX_ADAPTER_REF | 0e914bb |
-| MICRO_MANAGER_REF | v0.8.0 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | more-tests |
+| PRECICE_PRESET | production-audit |
| PRECICE_UID | 1003 |
| PRECICE_GID | 1003 |
## Information about the machine
### uname -a
-Linux precice-tests 5.15.0-177-generic #187-Ubuntu SMP Sat Apr 11 22:54:33 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
### lscpu
diff --git a/volume-coupled-diffusion/drain-fenics/run.sh b/volume-coupled-diffusion/drain-fenics/run.sh
index c519019d6..ef8d54901 100755
--- a/volume-coupled-diffusion/drain-fenics/run.sh
+++ b/volume-coupled-diffusion/drain-fenics/run.sh
@@ -6,9 +6,13 @@ exec > >(tee --append "$LOGFILE") 2>&1
if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
then
- python3 -m venv --system-site-packages .venv
- . .venv/bin/activate
- pip install -r ../solver-fenics/requirements.txt
+ if [ ! -d ".venv" ]; then
+ python3 -m venv --system-site-packages .venv
+ source .venv/bin/activate
+ pip install -r ../solver-fenics/requirements.txt
+ else
+ source .venv/bin/activate
+ fi
fi
python3 ../solver-fenics/volume-coupled-diffusion.py --drain
diff --git a/volume-coupled-diffusion/metadata.yaml b/volume-coupled-diffusion/metadata.yaml
new file mode 100644
index 000000000..c80aeca3f
--- /dev/null
+++ b/volume-coupled-diffusion/metadata.yaml
@@ -0,0 +1,20 @@
+name: Volume coupled diffusion
+path: volume-coupled-diffusion # relative to git repo
+url: https://precice.org/tutorials-volume-coupled-diffusion.html
+
+participants:
+ - Source
+ - Drain
+
+cases:
+ source-fenics:
+ participant: Source
+ directory: ./source-fenics
+ run: ./run.sh
+ component: fenics-adapter
+
+ drain-fenics:
+ participant: Drain
+ directory: ./drain-fenics
+ run: ./run.sh
+ component: fenics-adapter
diff --git a/volume-coupled-diffusion/reference-results/reference_results.metadata b/volume-coupled-diffusion/reference-results/reference_results.metadata
new file mode 100644
index 000000000..8f6d0ed50
--- /dev/null
+++ b/volume-coupled-diffusion/reference-results/reference_results.metadata
@@ -0,0 +1,71 @@
+
+
+# Reference Results
+
+This file contains an overview of the results over the reference results as well as the arguments used to generate them.
+We also include some information on the machine used to generate them
+
+## List of files
+
+| name | time | sha256 |
+|------|------|-------|
+| source-fenics_drain-fenics.tar.gz | 2026-05-31 00:09:19 | 5e6f023cd17fbd825c6deb2008a6c025d980dcf5a394b36a02c33f727bc14dd2 |
+
+## List of arguments used to generate the files
+
+| name | value |
+|------|------|
+| PLATFORM | ubuntu_2404 |
+| CALCULIX_VERSION | 2.20 |
+| DUNE_VERSION | 2.9 |
+| DUMUX_VERSION | 3.7 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | more-tests |
+| PRECICE_PRESET | production-audit |
+| PRECICE_UID | 1003 |
+| PRECICE_GID | 1003 |
+## Information about the machine
+
+### uname -a
+
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+
+
+### lscpu
+
+Architecture: x86_64
+CPU op-mode(s): 32-bit, 64-bit
+Address sizes: 45 bits physical, 48 bits virtual
+Byte Order: Little Endian
+CPU(s): 4
+On-line CPU(s) list: 0-3
+Vendor ID: GenuineIntel
+Model name: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz
+CPU family: 6
+Model: 85
+Thread(s) per core: 1
+Core(s) per socket: 1
+Socket(s): 4
+Stepping: 4
+BogoMIPS: 4199.99
+Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat pku ospke md_clear flush_l1d arch_capabilities
+Hypervisor vendor: VMware
+Virtualization type: full
+L1d cache: 128 KiB (4 instances)
+L1i cache: 128 KiB (4 instances)
+L2 cache: 4 MiB (4 instances)
+L3 cache: 88 MiB (4 instances)
+NUMA node(s): 1
+NUMA node0 CPU(s): 0-3
diff --git a/volume-coupled-diffusion/reference-results/source-fenics_drain-fenics.tar.gz b/volume-coupled-diffusion/reference-results/source-fenics_drain-fenics.tar.gz
new file mode 100644
index 000000000..716ab7383
--- /dev/null
+++ b/volume-coupled-diffusion/reference-results/source-fenics_drain-fenics.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:5e6f023cd17fbd825c6deb2008a6c025d980dcf5a394b36a02c33f727bc14dd2
+size 26670
diff --git a/volume-coupled-diffusion/source-fenics/run.sh b/volume-coupled-diffusion/source-fenics/run.sh
index 76b168162..2812b4fd9 100755
--- a/volume-coupled-diffusion/source-fenics/run.sh
+++ b/volume-coupled-diffusion/source-fenics/run.sh
@@ -6,9 +6,13 @@ exec > >(tee --append "$LOGFILE") 2>&1
if [ ! -v PRECICE_TUTORIALS_NO_VENV ]
then
- python3 -m venv --system-site-packages .venv
- . .venv/bin/activate
- pip install -r ../solver-fenics/requirements.txt
+ if [ ! -d ".venv" ]; then
+ python3 -m venv --system-site-packages .venv
+ source .venv/bin/activate
+ pip install -r ../solver-fenics/requirements.txt
+ else
+ source .venv/bin/activate
+ fi
fi
python3 ../solver-fenics/volume-coupled-diffusion.py --source
diff --git a/volume-coupled-flow/.gitignore b/volume-coupled-flow/.gitignore
new file mode 100644
index 000000000..1706a8443
--- /dev/null
+++ b/volume-coupled-flow/.gitignore
@@ -0,0 +1,2 @@
+# Signal file expected by the system tests specifically in uni-directional coupling
+fluid-participant-finished.log
\ No newline at end of file
diff --git a/volume-coupled-flow/README.md b/volume-coupled-flow/README.md
index b1cdf8992..bef36f747 100644
--- a/volume-coupled-flow/README.md
+++ b/volume-coupled-flow/README.md
@@ -33,7 +33,7 @@ Fluid participant:
Source participant:
-* Nutils. For more information, have a look at the [Nutils adapter documentation](https://precice.org/adapter-nutils.html). This Nutils solver requires at least Nutils v7.0.
+* Nutils. For more information, have a look at the [Nutils adapter documentation](https://precice.org/adapter-nutils.html).
## Running the simulation
diff --git a/volume-coupled-flow/fluid-openfoam/clean.sh b/volume-coupled-flow/fluid-openfoam/clean.sh
index b64fc5101..01efca4ae 100755
--- a/volume-coupled-flow/fluid-openfoam/clean.sh
+++ b/volume-coupled-flow/fluid-openfoam/clean.sh
@@ -4,3 +4,7 @@ set -e -u
. ../../tools/cleaning-tools.sh
clean_openfoam .
+
+# Necessary signal file for the system tests,
+# to keep the Source container running till the end
+rm -f ../fluid-participant-finished.log
\ No newline at end of file
diff --git a/volume-coupled-flow/fluid-openfoam/run.sh b/volume-coupled-flow/fluid-openfoam/run.sh
index ade8a7a98..5e97cbce6 100755
--- a/volume-coupled-flow/fluid-openfoam/run.sh
+++ b/volume-coupled-flow/fluid-openfoam/run.sh
@@ -11,3 +11,7 @@ topoSet
. ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs
close_log
+
+# Necessary signal file for the system tests,
+# to keep the Source container running till the end
+date > ../fluid-participant-finished.log
diff --git a/volume-coupled-flow/fluid-openfoam/system/controlDict b/volume-coupled-flow/fluid-openfoam/system/controlDict
index 65d2f9105..6c695213b 100644
--- a/volume-coupled-flow/fluid-openfoam/system/controlDict
+++ b/volume-coupled-flow/fluid-openfoam/system/controlDict
@@ -20,7 +20,7 @@ deltaT 0.005;
writeControl runTime;
-writeInterval 0.01;
+writeInterval 0.1;
purgeWrite 0;
diff --git a/volume-coupled-flow/metadata.yaml b/volume-coupled-flow/metadata.yaml
new file mode 100644
index 000000000..d6234cf05
--- /dev/null
+++ b/volume-coupled-flow/metadata.yaml
@@ -0,0 +1,20 @@
+name: Volume coupled flow
+path: volume-coupled-flow # relative to git repo
+url: https://precice.org/tutorials-volume-coupled-flow.html
+
+participants:
+ - Fluid
+ - Source
+
+cases:
+ fluid-openfoam:
+ participant: Fluid
+ directory: ./fluid-openfoam
+ run: ./run.sh
+ component: openfoam-adapter
+
+ source-nutils:
+ participant: Source
+ directory: ./source-nutils
+ run: PRECICE_TUTORIALS_TESTING="TRUE" ./run.sh
+ component: nutils-adapter
diff --git a/volume-coupled-flow/precice-config.xml b/volume-coupled-flow/precice-config.xml
index 5ce9631d5..e48a64360 100644
--- a/volume-coupled-flow/precice-config.xml
+++ b/volume-coupled-flow/precice-config.xml
@@ -21,7 +21,7 @@
-
+
-
+
-
+
-
-
+
+
diff --git a/volume-coupled-flow/reference-results/fluid-openfoam_source-nutils.tar.gz b/volume-coupled-flow/reference-results/fluid-openfoam_source-nutils.tar.gz
new file mode 100644
index 000000000..08e5747f2
--- /dev/null
+++ b/volume-coupled-flow/reference-results/fluid-openfoam_source-nutils.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:8fbbd006cd747915ebb2143029630b445668d352707a137622e30bd5e11f9313
+size 82379
diff --git a/volume-coupled-flow/reference-results/reference_results.metadata b/volume-coupled-flow/reference-results/reference_results.metadata
new file mode 100644
index 000000000..09128d30c
--- /dev/null
+++ b/volume-coupled-flow/reference-results/reference_results.metadata
@@ -0,0 +1,71 @@
+
+
+# Reference Results
+
+This file contains an overview of the results over the reference results as well as the arguments used to generate them.
+We also include some information on the machine used to generate them
+
+## List of files
+
+| name | time | sha256 |
+|------|------|-------|
+| fluid-openfoam_source-nutils.tar.gz | 2026-05-31 00:10:10 | 8fbbd006cd747915ebb2143029630b445668d352707a137622e30bd5e11f9313 |
+
+## List of arguments used to generate the files
+
+| name | value |
+|------|------|
+| PLATFORM | ubuntu_2404 |
+| CALCULIX_VERSION | 2.20 |
+| DUNE_VERSION | 2.9 |
+| DUMUX_VERSION | 3.7 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | more-tests |
+| PRECICE_PRESET | production-audit |
+| PRECICE_UID | 1003 |
+| PRECICE_GID | 1003 |
+## Information about the machine
+
+### uname -a
+
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+
+
+### lscpu
+
+Architecture: x86_64
+CPU op-mode(s): 32-bit, 64-bit
+Address sizes: 45 bits physical, 48 bits virtual
+Byte Order: Little Endian
+CPU(s): 4
+On-line CPU(s) list: 0-3
+Vendor ID: GenuineIntel
+Model name: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz
+CPU family: 6
+Model: 85
+Thread(s) per core: 1
+Core(s) per socket: 1
+Socket(s): 4
+Stepping: 4
+BogoMIPS: 4199.99
+Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat pku ospke md_clear flush_l1d arch_capabilities
+Hypervisor vendor: VMware
+Virtualization type: full
+L1d cache: 128 KiB (4 instances)
+L1i cache: 128 KiB (4 instances)
+L2 cache: 4 MiB (4 instances)
+L3 cache: 88 MiB (4 instances)
+NUMA node(s): 1
+NUMA node0 CPU(s): 0-3
diff --git a/volume-coupled-flow/source-nutils/requirements.txt b/volume-coupled-flow/source-nutils/requirements.txt
new file mode 100644
index 000000000..f22e7ac25
--- /dev/null
+++ b/volume-coupled-flow/source-nutils/requirements.txt
@@ -0,0 +1,4 @@
+setuptools>=69.0.0 # required by nutils
+nutils~=7.3
+numpy >1, <2
+pyprecice~=3.0
diff --git a/volume-coupled-flow/source-nutils/run.sh b/volume-coupled-flow/source-nutils/run.sh
index 243603b18..5d768edd7 100755
--- a/volume-coupled-flow/source-nutils/run.sh
+++ b/volume-coupled-flow/source-nutils/run.sh
@@ -4,6 +4,24 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
+fi
+
python3 source.py
+# System tests: Keep the container and the respective network alive till the end.
+if [[ -v PRECICE_TUTORIALS_TESTING ]]; then
+ echo "Waiting for the Fluid participant to finish..."
+ if [ ! -f "../fluid-participant-finished.log" ]; then
+ inotifywait -e create,modify,attrib --include '/fluid-participant-finished\.log$' -qq ..
+ fi
+fi
+
close_log
diff --git a/volume-coupled-flow/source-nutils/source.py b/volume-coupled-flow/source-nutils/source.py
index 42baabbbf..3683a049e 100644
--- a/volume-coupled-flow/source-nutils/source.py
+++ b/volume-coupled-flow/source-nutils/source.py
@@ -30,7 +30,7 @@ def main():
ns.x = geom
# preCICE setup
- participant = precice.Participant("Source-Velocity", "../precice-config.xml", 0, 1)
+ participant = precice.Participant("Source", "../precice-config.xml", 0, 1)
# define coupling mesh
mesh_name = "Source-Mesh"
diff --git a/water-hammer/fluid1d-left-nutils/requirements.txt b/water-hammer/fluid1d-left-nutils/requirements.txt
index 721a30444..34177a257 100644
--- a/water-hammer/fluid1d-left-nutils/requirements.txt
+++ b/water-hammer/fluid1d-left-nutils/requirements.txt
@@ -1,6 +1,6 @@
-setuptools # required by nutils
+setuptools>=69.0.0 # required by nutils
nutils~=9.0
numpy >1, <2
pyprecice~=3.0
-matplotlib
-treelog
\ No newline at end of file
+matplotlib>=3.5,<4
+treelog>=1,<2
\ No newline at end of file
diff --git a/water-hammer/fluid1d-left-nutils/run.sh b/water-hammer/fluid1d-left-nutils/run.sh
index 4e978edf1..4e3e431f5 100755
--- a/water-hammer/fluid1d-left-nutils/run.sh
+++ b/water-hammer/fluid1d-left-nutils/run.sh
@@ -4,9 +4,15 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-python3 -m venv .venv
-. .venv/bin/activate
-pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
+fi
NUTILS_RICHOUTPUT=no python3 ../solver-fluid1d-nutils/Fluid1D.py side=Left
diff --git a/water-hammer/fluid1d-right-nutils/requirements.txt b/water-hammer/fluid1d-right-nutils/requirements.txt
index 721a30444..34177a257 100644
--- a/water-hammer/fluid1d-right-nutils/requirements.txt
+++ b/water-hammer/fluid1d-right-nutils/requirements.txt
@@ -1,6 +1,6 @@
-setuptools # required by nutils
+setuptools>=69.0.0 # required by nutils
nutils~=9.0
numpy >1, <2
pyprecice~=3.0
-matplotlib
-treelog
\ No newline at end of file
+matplotlib>=3.5,<4
+treelog>=1,<2
\ No newline at end of file
diff --git a/water-hammer/fluid1d-right-nutils/run.sh b/water-hammer/fluid1d-right-nutils/run.sh
index e064d1e66..72b0163b1 100755
--- a/water-hammer/fluid1d-right-nutils/run.sh
+++ b/water-hammer/fluid1d-right-nutils/run.sh
@@ -4,9 +4,15 @@ set -e -u
. ../../tools/log.sh
exec > >(tee --append "$LOGFILE") 2>&1
-python3 -m venv .venv
-. .venv/bin/activate
-pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
+fi
NUTILS_RICHOUTPUT=no python3 ../solver-fluid1d-nutils/Fluid1D.py side=Right
diff --git a/water-hammer/metadata.yaml b/water-hammer/metadata.yaml
new file mode 100644
index 000000000..0484cc7e1
--- /dev/null
+++ b/water-hammer/metadata.yaml
@@ -0,0 +1,34 @@
+name: Water hammer
+path: water-hammer # relative to git repo
+url: https://precice.org/tutorials-water-hammer.html
+
+participants:
+ - Fluid1DLeft
+ # - Fluid1DRight
+ # - Fluid3DLeft
+ - Fluid3DRight
+
+cases:
+ fluid1d-left-nutils:
+ participant: Fluid1DLeft
+ directory: ./fluid1d-left-nutils
+ run: ./run.sh
+ component: nutils-adapter
+
+ # fluid1d-right-nutils:
+ # participant: Fluid1DRight
+ # directory: ./fluid1d-right-nutils
+ # run: ./run.sh
+ # component: nutils-adapter
+
+ # fluid3d-left-openfoam:
+ # participant: Fluid3DLeft
+ # directory: ./fluid3d-left-openfoam
+ # run: ./run.sh
+ # component: openfoam-adapter
+
+ fluid3d-right-openfoam:
+ participant: Fluid3DRight
+ directory: ./fluid3d-right-openfoam
+ run: ./run.sh
+ component: openfoam-adapter
diff --git a/water-hammer/precice-config-1d-1d.xml b/water-hammer/precice-config-1d-1d.xml
index b0362ad8c..0e8fc0a83 100644
--- a/water-hammer/precice-config-1d-1d.xml
+++ b/water-hammer/precice-config-1d-1d.xml
@@ -32,7 +32,6 @@
from="Fluid1DRight-Mesh"
to="Fluid1DLeft-Mesh"
constraint="consistent" />
-
@@ -45,7 +44,6 @@
from="Fluid1DLeft-Mesh"
to="Fluid1DRight-Mesh"
constraint="consistent" />
-
diff --git a/water-hammer/precice-config-1d-3d.xml b/water-hammer/precice-config-1d-3d.xml
index 0518bf91e..87cd7ddd6 100644
--- a/water-hammer/precice-config-1d-3d.xml
+++ b/water-hammer/precice-config-1d-3d.xml
@@ -38,7 +38,6 @@
from="Fluid3DRight-Mesh"
to="Fluid1DLeft-Mesh"
constraint="consistent" />
-
@@ -57,7 +56,6 @@
from="Fluid1DLeft-Mesh"
to="Fluid3DRight-Mesh"
constraint="consistent" />
-
diff --git a/water-hammer/precice-config-3d-1d.xml b/water-hammer/precice-config-3d-1d.xml
index 42f506424..464e45a52 100644
--- a/water-hammer/precice-config-3d-1d.xml
+++ b/water-hammer/precice-config-3d-1d.xml
@@ -38,7 +38,6 @@
from="Fluid3DLeft-Mesh"
to="Fluid1DRight-Mesh"
constraint="consistent" />
-
@@ -57,7 +56,6 @@
from="Fluid1DRight-Mesh"
to="Fluid3DLeft-Mesh"
constraint="consistent" />
-
diff --git a/water-hammer/precice-config-3d-3d.xml b/water-hammer/precice-config-3d-3d.xml
index a96064f08..7c9ef2cc3 100644
--- a/water-hammer/precice-config-3d-3d.xml
+++ b/water-hammer/precice-config-3d-3d.xml
@@ -32,7 +32,6 @@
from="Fluid3DLeft-Mesh"
to="Fluid3DRight-Mesh"
constraint="consistent" />
-
@@ -45,7 +44,6 @@
from="Fluid3DRight-Mesh"
to="Fluid3DLeft-Mesh"
constraint="consistent" />
-
diff --git a/water-hammer/reference-results/fluid1d-left-nutils_fluid3d-right-openfoam.tar.gz b/water-hammer/reference-results/fluid1d-left-nutils_fluid3d-right-openfoam.tar.gz
new file mode 100644
index 000000000..21eee0f3a
--- /dev/null
+++ b/water-hammer/reference-results/fluid1d-left-nutils_fluid3d-right-openfoam.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b3c96d4bcd10a6447e39b2918c94753cd9f1994cba89abf713b21869fc78c7dd
+size 159892
diff --git a/water-hammer/reference-results/reference_results.metadata b/water-hammer/reference-results/reference_results.metadata
new file mode 100644
index 000000000..8452887b4
--- /dev/null
+++ b/water-hammer/reference-results/reference_results.metadata
@@ -0,0 +1,71 @@
+
+
+# Reference Results
+
+This file contains an overview of the results over the reference results as well as the arguments used to generate them.
+We also include some information on the machine used to generate them
+
+## List of files
+
+| name | time | sha256 |
+|------|------|-------|
+| fluid1d-left-nutils_fluid3d-right-openfoam.tar.gz | 2026-05-31 00:21:36 | b3c96d4bcd10a6447e39b2918c94753cd9f1994cba89abf713b21869fc78c7dd |
+
+## List of arguments used to generate the files
+
+| name | value |
+|------|------|
+| PLATFORM | ubuntu_2404 |
+| CALCULIX_VERSION | 2.20 |
+| DUNE_VERSION | 2.9 |
+| DUMUX_VERSION | 3.7 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | more-tests |
+| PRECICE_PRESET | production-audit |
+| PRECICE_UID | 1003 |
+| PRECICE_GID | 1003 |
+## Information about the machine
+
+### uname -a
+
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+
+
+### lscpu
+
+Architecture: x86_64
+CPU op-mode(s): 32-bit, 64-bit
+Address sizes: 45 bits physical, 48 bits virtual
+Byte Order: Little Endian
+CPU(s): 4
+On-line CPU(s) list: 0-3
+Vendor ID: GenuineIntel
+Model name: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz
+CPU family: 6
+Model: 85
+Thread(s) per core: 1
+Core(s) per socket: 1
+Socket(s): 4
+Stepping: 4
+BogoMIPS: 4199.99
+Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat pku ospke md_clear flush_l1d arch_capabilities
+Hypervisor vendor: VMware
+Virtualization type: full
+L1d cache: 128 KiB (4 instances)
+L1i cache: 128 KiB (4 instances)
+L2 cache: 4 MiB (4 instances)
+L3 cache: 88 MiB (4 instances)
+NUMA node(s): 1
+NUMA node0 CPU(s): 0-3
diff --git a/wolf-sheep-soil-creep/README.md b/wolf-sheep-soil-creep/README.md
new file mode 100644
index 000000000..b084c7285
--- /dev/null
+++ b/wolf-sheep-soil-creep/README.md
@@ -0,0 +1,58 @@
+---
+title: Wolf-sheep-grass model with soil creep
+permalink: tutorials-wolf-sheep-soil-creep.html
+keywords: MESA, Landlab, wolf-sheep-grass, soil creep, ABM, agent-based modeling
+summary: Example of bi-directional ABM-PDE coupling via preCICE.
+---
+
+{% note %}
+Get the [case files of this tutorial](https://github.com/precice/tutorials/tree/develop/wolf-sheep-soil-creep), as continuously rendered here, or see the [latest released version](https://github.com/precice/tutorials/tree/master/wolf-sheep-soil-creep) (if there is already one). Read how in the [tutorials introduction](https://precice.org/tutorials.html).
+{% endnote %}
+
+## Setup
+
+This tutorial is based on Landlab's [Wolf-Sheep-Grass Model with Soil Creep](https://landlab.csdms.io/tutorials/agent_based_modeling/wolf_sheep/wolf_sheep_with_soil_creep.html) example, which couples the [Wolf-Sheep model from Mesa](https://mesa.readthedocs.io/latest/examples/advanced/wolf_sheep.html) with a Landlab soil creep model in a single notebook-based workflow. The [source notebook](https://github.com/landlab/landlab/blob/master/docs/source/tutorials/agent_based_modeling/wolf_sheep/wolf_sheep_with_soil_creep.ipynb) is licensed under [MIT](https://landlab.csdms.io/about/license.html).
+
+The purpose of this tutorial is to demonstrate a simple two-way coupling between an agent-based model (ABM) and a grid-based continuum model via preCICE. The example extends the canonical wolf-sheep-grass ABM with a simple soil-creep feedback on a shared sloping raster grid. When sheep eat grass, the soil beneath the damaged grass becomes more mobile, increasing the local soil transport efficiency and affecting downslope soil transport. The feedback also acts in the other direction: soil thickness affects grass growth by preventing grass from growing where the soil becomes too thin.
+
+In this implementation, the Mesa wolf-sheep-grass model and the Landlab soil creep model are two separate preCICE participants, exchanging grass cover and soil depth during the simulation. The Mesa participant extracts the current grass map from the wolf-sheep-grass model and sends it to the Landlab participant. The Landlab participant uses this grass map to adapt the soil creep coefficient, evolves the soil thickness, and sends the updated soil depth back to the Mesa participant, where it is used to limit grass growth. This example is intentionally simple and should be understood as a demonstration case for coupling ABM and PDE-style models via preCICE, rather than as a physically calibrated landscape evolution model.
+
+## Configuration
+
+preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)):
+
+
+
+## Available solvers
+
+Soil-Creep PDE participant:
+
+* Landlab. Numerical modeling of Earth surface dynamics. For more information, have a look at the [Landlab documentation](https://landlab.csdms.io/index.html).
+
+Wolf-Sheep-Grass ABM participant:
+
+* MESA. Agent-based modeling (or ABM) framework. For more information have a look at the [MESA documentation](https://mesa.readthedocs.io/latest/index.html)
+
+## Running the simulation
+
+Open two separate terminals and start the soil creep and wolf sheep participants by calling the respective run scripts `run.sh` located in each of the participants' directories. For example:
+
+```bash
+cd soil-creep-landlab
+./run.sh
+```
+
+and
+
+```bash
+cd wolf-sheep-grass-mesa
+./run.sh
+```
+
+## Post-processing
+
+The soil-creep participant generates Python-based visualizations, which are written to `soil-creep-landlab/output`. The following examples were generated by setting `rng=42` in the `WolfSheepScenario` for the wolf-sheep-grass participant.
+
+
+
+
diff --git a/wolf-sheep-soil-creep/clean-tutorial.sh b/wolf-sheep-soil-creep/clean-tutorial.sh
new file mode 120000
index 000000000..4713f5092
--- /dev/null
+++ b/wolf-sheep-soil-creep/clean-tutorial.sh
@@ -0,0 +1 @@
+../tools/clean-tutorial-base.sh
\ No newline at end of file
diff --git a/wolf-sheep-soil-creep/images/tutorials-wolf-sheep-soil-creep-erosion_deposition_patterns.png b/wolf-sheep-soil-creep/images/tutorials-wolf-sheep-soil-creep-erosion_deposition_patterns.png
new file mode 100644
index 000000000..718cabee7
Binary files /dev/null and b/wolf-sheep-soil-creep/images/tutorials-wolf-sheep-soil-creep-erosion_deposition_patterns.png differ
diff --git a/wolf-sheep-soil-creep/images/tutorials-wolf-sheep-soil-creep-grass_map.png b/wolf-sheep-soil-creep/images/tutorials-wolf-sheep-soil-creep-grass_map.png
new file mode 100644
index 000000000..4fae85a0c
Binary files /dev/null and b/wolf-sheep-soil-creep/images/tutorials-wolf-sheep-soil-creep-grass_map.png differ
diff --git a/wolf-sheep-soil-creep/images/tutorials-wolf-sheep-soil-creep-precice-config.png b/wolf-sheep-soil-creep/images/tutorials-wolf-sheep-soil-creep-precice-config.png
new file mode 100644
index 000000000..f39e09e5a
Binary files /dev/null and b/wolf-sheep-soil-creep/images/tutorials-wolf-sheep-soil-creep-precice-config.png differ
diff --git a/wolf-sheep-soil-creep/images/tutorials-wolf-sheep-soil-creep-soil_thickness.png b/wolf-sheep-soil-creep/images/tutorials-wolf-sheep-soil-creep-soil_thickness.png
new file mode 100644
index 000000000..0bb5d8801
Binary files /dev/null and b/wolf-sheep-soil-creep/images/tutorials-wolf-sheep-soil-creep-soil_thickness.png differ
diff --git a/wolf-sheep-soil-creep/metadata.yaml b/wolf-sheep-soil-creep/metadata.yaml
new file mode 100644
index 000000000..574c7f922
--- /dev/null
+++ b/wolf-sheep-soil-creep/metadata.yaml
@@ -0,0 +1,20 @@
+name: Wolf-sheep-grass soil creep
+path: wolf-sheep-soil-creep
+url: https://precice.org/tutorials-wolf-sheep-soil-creep.html
+
+participants:
+ - Soil-Creep
+ - Wolf-Sheep-Grass
+
+cases:
+ soil-creep-landlab:
+ participant: Soil-Creep
+ directory: ./soil-creep-landlab
+ run: ./run.sh
+ component: python-bindings
+
+ wolf-sheep-grass-mesa:
+ participant: Wolf-Sheep-Grass
+ directory: ./wolf-sheep-grass-mesa
+ run: ./run.sh
+ component: python-bindings
diff --git a/wolf-sheep-soil-creep/precice-config.xml b/wolf-sheep-soil-creep/precice-config.xml
new file mode 100644
index 000000000..2d988c5ff
--- /dev/null
+++ b/wolf-sheep-soil-creep/precice-config.xml
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/wolf-sheep-soil-creep/reference-results/reference_results.metadata b/wolf-sheep-soil-creep/reference-results/reference_results.metadata
new file mode 100644
index 000000000..07b011e47
--- /dev/null
+++ b/wolf-sheep-soil-creep/reference-results/reference_results.metadata
@@ -0,0 +1,71 @@
+
+
+# Reference Results
+
+This file contains an overview of the results over the reference results as well as the arguments used to generate them.
+We also include some information on the machine used to generate them
+
+## List of files
+
+| name | time | sha256 |
+|------|------|-------|
+| soil-creep-landlab_wolf-sheep-grass-mesa.tar.gz | 2026-06-01 12:01:54 | 6726ec7e3db23bd0cad8cecbd356eefae87b63b2f189e53af6e45f5ef7d828c3 |
+
+## List of arguments used to generate the files
+
+| name | value |
+|------|------|
+| PLATFORM | ubuntu_2404 |
+| CALCULIX_VERSION | 2.20 |
+| DUNE_VERSION | 2.9 |
+| DUMUX_VERSION | 3.7 |
+| OPENFOAM_EXECUTABLE | openfoam2512 |
+| SU2_VERSION | 7.5.1 |
+| FENICS_ADAPTER_REF | v2.3.0 |
+| CALCULIX_ADAPTER_REF | v2.20.1 |
+| DEALII_ADAPTER_REF | a421d92 |
+| DUMUX_ADAPTER_REF | 3f3f54f |
+| MICRO_MANAGER_REF | v0.10.1 |
+| OPENFOAM_ADAPTER_REF | 2c3062c |
+| PRECICE_REF | v3.4.1 |
+| PYTHON_BINDINGS_REF | v3.4.0 |
+| SU2_ADAPTER_REF | 5abe79b |
+| TUTORIALS_REF | develop |
+| PRECICE_PRESET | production-audit |
+| PRECICE_UID | 1003 |
+| PRECICE_GID | 1003 |
+## Information about the machine
+
+### uname -a
+
+Linux precice-tests 5.15.0-179-generic #189-Ubuntu SMP Tue May 5 18:20:56 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
+
+
+### lscpu
+
+Architecture: x86_64
+CPU op-mode(s): 32-bit, 64-bit
+Address sizes: 45 bits physical, 48 bits virtual
+Byte Order: Little Endian
+CPU(s): 4
+On-line CPU(s) list: 0-3
+Vendor ID: GenuineIntel
+Model name: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz
+CPU family: 6
+Model: 85
+Thread(s) per core: 1
+Core(s) per socket: 1
+Socket(s): 4
+Stepping: 4
+BogoMIPS: 4199.99
+Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat pku ospke md_clear flush_l1d arch_capabilities
+Hypervisor vendor: VMware
+Virtualization type: full
+L1d cache: 128 KiB (4 instances)
+L1i cache: 128 KiB (4 instances)
+L2 cache: 4 MiB (4 instances)
+L3 cache: 88 MiB (4 instances)
+NUMA node(s): 1
+NUMA node0 CPU(s): 0-3
diff --git a/wolf-sheep-soil-creep/reference-results/soil-creep-landlab_wolf-sheep-grass-mesa.tar.gz b/wolf-sheep-soil-creep/reference-results/soil-creep-landlab_wolf-sheep-grass-mesa.tar.gz
new file mode 100644
index 000000000..3e467fab2
--- /dev/null
+++ b/wolf-sheep-soil-creep/reference-results/soil-creep-landlab_wolf-sheep-grass-mesa.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6726ec7e3db23bd0cad8cecbd356eefae87b63b2f189e53af6e45f5ef7d828c3
+size 49721
diff --git a/wolf-sheep-soil-creep/soil-creep-landlab/clean.sh b/wolf-sheep-soil-creep/soil-creep-landlab/clean.sh
new file mode 100755
index 000000000..ebce578f2
--- /dev/null
+++ b/wolf-sheep-soil-creep/soil-creep-landlab/clean.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env sh
+set -e -u
+
+rm -rfv ./output/
+
+. ../../tools/cleaning-tools.sh
+
+clean_precice_logs .
+clean_case_logs .
diff --git a/wolf-sheep-soil-creep/soil-creep-landlab/requirements.txt b/wolf-sheep-soil-creep/soil-creep-landlab/requirements.txt
new file mode 100644
index 000000000..b414e0236
--- /dev/null
+++ b/wolf-sheep-soil-creep/soil-creep-landlab/requirements.txt
@@ -0,0 +1,4 @@
+numpy >1, <2
+matplotlib>=3.5,<4
+landlab>=2.0,<3
+pyprecice~=3.0
diff --git a/wolf-sheep-soil-creep/soil-creep-landlab/run.sh b/wolf-sheep-soil-creep/soil-creep-landlab/run.sh
new file mode 100755
index 000000000..6cfe51b1c
--- /dev/null
+++ b/wolf-sheep-soil-creep/soil-creep-landlab/run.sh
@@ -0,0 +1,21 @@
+#!/usr/bin/env bash
+set -e -u
+
+. ../../tools/log.sh
+
+exec > >(tee --append "$LOGFILE") 2>&1
+
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
+fi
+
+mkdir -p output
+python3 soil_creep.py
+
+close_log
diff --git a/wolf-sheep-soil-creep/soil-creep-landlab/soil_creep.py b/wolf-sheep-soil-creep/soil-creep-landlab/soil_creep.py
new file mode 100644
index 000000000..2f17e3830
--- /dev/null
+++ b/wolf-sheep-soil-creep/soil-creep-landlab/soil_creep.py
@@ -0,0 +1,122 @@
+import copy
+import matplotlib as mpl
+import matplotlib.pyplot as plt
+import numpy as np
+from landlab import RasterModelGrid, imshow_grid
+from landlab.components import LinearDiffuser
+import precice
+
+initial_soil_depth = 0.3
+
+# Set the soil-thickness scale for limiting creep where little soil is available
+hstar = 0.2
+
+# Set parameters for two soil creep coefficients: slow (full grass cover) and fast (partial or "eaten" grass cover)
+fast_creep = 0.1
+slow_creep = 0.001
+
+ground_cover_cmap = copy.copy(mpl.colormaps["YlGn"])
+
+# Create a grid the same size as the W-S-G model's grid
+width = 20
+height = 20
+
+rmg = RasterModelGrid((width, height))
+
+# Create elevation field and have it slope down to the south at 10% gradient
+elev = rmg.add_zeros("topographic__elevation", at="node")
+elev[:] = 0.1 * rmg.y_of_node
+
+# Have one open boundary on the south side
+rmg.set_closed_boundaries_at_grid_edges(True, True, True, False)
+
+# Remember the starting elevation so we can calculate cumulative erosion/deposition
+initial_elev = np.zeros(rmg.number_of_nodes)
+initial_elev[:] = elev
+
+# Also remember the elevation of the prior time step, so we can difference
+prior_elev = np.zeros(rmg.number_of_nodes)
+
+# Create a field for the creep coefficient
+creep_coef = rmg.add_zeros("creep_coefficient", at="node")
+
+# Create a soil-thickness field
+soil = rmg.add_zeros("soil__depth", at="node")
+soil[:] = initial_soil_depth
+
+# Instantiate a LinearDiffuser (soil creep) Landlab component
+diffuser = LinearDiffuser(rmg, linear_diffusivity=creep_coef)
+
+# preCICE setup
+participant_name = "Soil-Creep"
+config_file_name = "../precice-config.xml"
+solver_process_index = 0
+solver_process_size = 1
+participant = precice.Participant(participant_name, config_file_name, solver_process_index, solver_process_size)
+
+positions = [[x, y] for x in range(width) for y in range(height)]
+vertex_gm_ids = participant.set_mesh_vertices("Soil-Creep-Mesh", positions)
+vertex_soil_ids = participant.set_mesh_vertices("Soil-Depth-Mesh", positions)
+
+participant.initialize()
+
+while participant.is_coupling_ongoing():
+ solver_dt = 0.2 * rmg.dx * rmg.dx / fast_creep
+ precice_dt = participant.get_max_time_step_size()
+ dt = np.minimum(solver_dt, precice_dt)
+
+ gm = participant.read_data("Soil-Creep-Mesh", "Grass", vertex_gm_ids, dt)
+
+ # Assign the higher creep coefficient to cells where the grass has
+ # been eaten and not yet recovered; the slower value is assigned to
+ # "fully grown" grass patches.
+ creep_coef[gm.flatten() == 1] = fast_creep
+ creep_coef[gm.flatten() == 2] = slow_creep
+
+ # Limit the creep coefficient according to the soil-thickness field, so absent soil cannot move.
+ creep_coef *= 1.0 - np.exp(-soil / hstar)
+
+ # Remember the current elevation before LinearDiffuser updates the grid's
+ # topographic__elevation field in place.
+ prior_elev[:] = elev
+
+ # Run the soil-creep model
+ diffuser.run_one_step(dt)
+
+ # Update the soil cover
+ soil += elev - prior_elev
+
+ participant.write_data("Soil-Depth-Mesh", "Soil", vertex_soil_ids, soil)
+
+ participant.advance(dt)
+
+participant.finalize()
+
+# Calculate and plot the erosion/deposition patterns
+plt.figure()
+ero_dep = elev - initial_elev
+maxchange = np.amax(np.abs(ero_dep))
+imshow_grid(
+ rmg,
+ ero_dep,
+ vmin=-maxchange,
+ vmax=maxchange,
+ cmap="coolwarm_r",
+ colorbar_label="Depth of soil accumulation (+) or loss (-), m",
+)
+plt.savefig("output/erosion_deposition_patterns.png")
+plt.close()
+
+# Soil thickness
+plt.figure()
+imshow_grid(rmg, soil, colorbar_label="Soil thickness, m")
+plt.savefig("output/soil_thickness.png")
+plt.close()
+
+# Ground cover
+plt.figure()
+imshow_grid(
+ rmg, gm, cmap=ground_cover_cmap, colorbar_label="Ground cover (1 = bare, 2 = grass)"
+)
+plt.savefig("output/grass_map.png")
+plt.close()
diff --git a/wolf-sheep-soil-creep/wolf-sheep-grass-mesa/clean.sh b/wolf-sheep-soil-creep/wolf-sheep-grass-mesa/clean.sh
new file mode 100755
index 000000000..494c80414
--- /dev/null
+++ b/wolf-sheep-soil-creep/wolf-sheep-grass-mesa/clean.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env sh
+set -e -u
+
+. ../../tools/cleaning-tools.sh
+
+clean_precice_logs .
+clean_case_logs .
diff --git a/wolf-sheep-soil-creep/wolf-sheep-grass-mesa/requirements.txt b/wolf-sheep-soil-creep/wolf-sheep-grass-mesa/requirements.txt
new file mode 100644
index 000000000..355f9e10d
--- /dev/null
+++ b/wolf-sheep-soil-creep/wolf-sheep-grass-mesa/requirements.txt
@@ -0,0 +1,5 @@
+numpy >1, <2
+matplotlib>=3.5,<4
+mesa>=3,<4
+pyprecice~=3.0
+networkx>=3,<4
diff --git a/wolf-sheep-soil-creep/wolf-sheep-grass-mesa/run.sh b/wolf-sheep-soil-creep/wolf-sheep-grass-mesa/run.sh
new file mode 100755
index 000000000..3ff1a9459
--- /dev/null
+++ b/wolf-sheep-soil-creep/wolf-sheep-grass-mesa/run.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+set -e -u
+
+. ../../tools/log.sh
+
+exec > >(tee --append "$LOGFILE") 2>&1
+
+if [ ! -v PRECICE_TUTORIALS_NO_VENV ]; then
+ if [ ! -d ".venv" ]; then
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install -r requirements.txt && pip freeze > pip-installed-packages.log
+ else
+ source .venv/bin/activate
+ fi
+fi
+
+python3 wolf_sheep_grass.py
+
+close_log
diff --git a/wolf-sheep-soil-creep/wolf-sheep-grass-mesa/wolf_sheep_grass.py b/wolf-sheep-soil-creep/wolf-sheep-grass-mesa/wolf_sheep_grass.py
new file mode 100644
index 000000000..54b267e4e
--- /dev/null
+++ b/wolf-sheep-soil-creep/wolf-sheep-grass-mesa/wolf_sheep_grass.py
@@ -0,0 +1,97 @@
+from mesa.examples.advanced.wolf_sheep.agents import GrassPatch
+from mesa.examples.advanced.wolf_sheep.model import WolfSheep
+from mesa.examples.advanced.wolf_sheep.model import WolfSheepScenario
+import copy
+import matplotlib as mpl
+import matplotlib.pyplot as plt
+import numpy as np
+import precice
+
+min_depth_for_grass = 0.2
+
+# Use the same time step size as the Soil-Creep participant
+solver_dt = 2.0
+
+# Initialize Wolf-Sheep-Grass model
+wss = WolfSheepScenario(
+ initial_sheep=20,
+ initial_wolves=10,
+ grass=True,
+ grass_regrowth_time=15, # give grass a fighting chance...
+ rng=42, # fixed seed for reproducible results
+)
+ws = WolfSheep(wss)
+
+ground_cover_cmap = copy.copy(mpl.colormaps["YlGn"])
+
+
+def generate_grass_map(model):
+ grass_map = np.zeros((model.grid.width, model.grid.height))
+ for cell in model.grid:
+ (x, y) = cell.coordinate
+ cell_content = cell.agents
+ for agent in cell_content:
+ if type(agent) is GrassPatch:
+ if agent.fully_grown:
+ grass_map[x][y] = 2
+ else:
+ grass_map[x][y] = 1
+ return grass_map
+
+
+def plot_grass_map(grass_map):
+ plt.imshow(grass_map, interpolation="nearest", cmap=ground_cover_cmap)
+ plt.colorbar()
+
+
+def limit_grass_by_soil(wsg_model, soil, min_soil_depth):
+ soilmatrix = soil.reshape((wsg_model.width, wsg_model.height))
+ for cell in wsg_model.grid:
+ (x, y) = cell.coordinate
+ cell_content = cell.agents
+ if soilmatrix[x][y] < min_soil_depth:
+ for agent in cell_content:
+ if type(agent) is GrassPatch:
+ agent.fully_grown = False
+
+
+width = ws.grid.width
+height = ws.grid.height
+
+# preCICE setup
+participant_name = "Wolf-Sheep-Grass"
+config_file_name = "../precice-config.xml"
+solver_process_index = 0
+solver_process_size = 1
+participant = precice.Participant(participant_name, config_file_name, solver_process_index, solver_process_size)
+
+positions = [[x, y] for x in range(width) for y in range(height)]
+vertex_gm_ids = participant.set_mesh_vertices("Wolf-Sheep-Grass-Mesh", positions)
+vertex_soil_ids = participant.set_mesh_vertices("Soil-Grass-Mesh", positions)
+
+soil = np.zeros([width * height])
+
+if participant.requires_initial_data():
+ gm = generate_grass_map(ws)
+ participant.write_data("Wolf-Sheep-Grass-Mesh", "Grass", vertex_gm_ids, gm.flatten())
+
+participant.initialize()
+
+while participant.is_coupling_ongoing():
+ precice_dt = participant.get_max_time_step_size()
+ dt = np.minimum(solver_dt, precice_dt)
+
+ soil = participant.read_data("Soil-Grass-Mesh", "Soil", vertex_soil_ids, dt)
+
+ # Update the grass cover
+ limit_grass_by_soil(ws, soil, min_depth_for_grass)
+
+ # Run the W-S-G model
+ ws.step()
+
+ gm = generate_grass_map(ws)
+ participant.write_data("Wolf-Sheep-Grass-Mesh", "Grass", vertex_gm_ids, gm.flatten())
+
+ participant.advance(dt)
+
+participant.finalize()